mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-14 21:38:34 +00:00
add js to tree
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3693 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
855c7b9a77
commit
fff98f6316
1137 files changed
+386873
No files matched your search
@@ -0,0 +1,18 @@
|
||||
/MANIFEST/1.1/Thu Jun 4 22:51:07 1998//
|
||||
/MacErrorHandling.h/3.4/Sun Apr 25 15:00:59 2004//
|
||||
/macdll.c/3.12/Sun Apr 25 15:00:59 2004//
|
||||
/macdll.h/1.5/Sun Apr 25 15:00:59 2004//
|
||||
/macio.c/3.37/Sun Apr 25 15:00:59 2004//
|
||||
/macio.h/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/macrng.c/1.7/Sun Apr 25 15:00:59 2004//
|
||||
/macsocket.h/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/macsockotpt.c/3.42/Sun Apr 25 15:00:59 2004//
|
||||
/macthr.c/3.22/Sun Apr 25 15:00:59 2004//
|
||||
/mactime.c/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/mactime.h/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/mdcriticalregion.c/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/mdcriticalregion.h/1.3/Sun Apr 25 15:00:59 2004//
|
||||
/mdmac.c/3.20/Mon Nov 7 22:39:01 2005//
|
||||
/mdmac.h/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/prcpucfg.h/3.11/Sun Apr 25 15:00:59 2004//
|
||||
D
|
||||
@@ -0,0 +1 @@
|
||||
mozilla/nsprpub/pr/src/md/mac
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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__ */
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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___ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(¤tTime);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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___ */
|
||||
|
||||
@@ -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_GetCurrentThread();
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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___ */
|
||||
Reference in new issue
Block a user