aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/HostControl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/HostControl.cpp')
-rw-r--r--SrcShared/HostControl.cpp4989
1 files changed, 4989 insertions, 0 deletions
diff --git a/SrcShared/HostControl.cpp b/SrcShared/HostControl.cpp
new file mode 100644
index 0000000..7cb505e
--- /dev/null
+++ b/SrcShared/HostControl.cpp
@@ -0,0 +1,4989 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "HostControl.h"
+#include "HostControlPrv.h"
+
+#include "DebugMgr.h" // gDebuggerGlobals
+#include "EmApplication.h" // gApplication, ScheduleQuit
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmCPU68K.h" // gCPU68K, gStackHigh, etc.
+#include "EmDirRef.h" // EmDirRefList
+#include "EmDlg.h" // DoGetFile, DoPutFile, DoGetDirectory
+#include "EmDocument.h" // gDocument, HostSaveScreen, ScheduleNewHorde
+#include "EmErrCodes.h" // kError_NoError
+#include "EmExgMgr.h" // EmExgMgr::GetExgMgr
+#include "EmFileImport.h" // EmFileImport::LoadPalmFileList
+#include "EmFileRef.h" // EmFileRefList
+#include "EmMemory.h" // EmMem_strlen, EmMem_strcpy
+#include "EmPalmStructs.h" // EmAliasErr
+#include "EmPatchState.h" // EmPatchState::UIInitialized
+#include "EmRPC.h" // RPC::HandlingPacket, RPC::DeferCurrentPacket
+#include "EmSession.h" // ResumeByExternal
+#include "EmStreamFile.h" // EmStreamFile
+#include "EmStructs.h" // StringList, ByteList
+#include "Hordes.h" // Hordes::IsOn
+#include "LoadApplication.h" // SavePalmFile
+#include "Logging.h" // LogFile
+#include "Miscellaneous.h" // GetDeviceTextList, GetMemoryTextList
+#include "Platform.h" // Platform::GetShortVersionString
+#include "Profiling.h" // ProfileInit, ProfileStart, ProfileStop, etc.
+#include "ROMStubs.h" // EvtWakeup
+#include "Strings.r.h" // kStr_ProfileResults
+
+#include <ctype.h> // isdigit
+
+#if HAS_TRACER
+#include "TracerPlatform.h" // Tracer
+#endif
+
+
+#include "EmSubroutine.h"
+#include "Marshal.h"
+
+#define CALLED_GET_PARAM_FILE(name) \
+ CALLED_GET_PARAM_VAL (emuptr, name); \
+ \
+ FILE* fh = PrvToFILE (name)
+
+
+#if PLATFORM_WINDOWS
+
+#include <direct.h> // _mkdir, _rmdir
+#include <sys/types.h> //
+#include <sys/stat.h> // struct _stat
+#include <sys/utime.h> // _utime, _utimbuf
+#include <io.h> // _open
+#include <fcntl.h> // O_RDWR
+#include <time.h> // asctime, clock, clock_t, etc.
+
+typedef struct _stat _stat_;
+typedef struct _utimbuf _utimbuf_;
+
+#else
+
+#include "sys/stat.h" // mkdir(???), stat
+#include "unistd.h" // rmdir
+#include "fcntl.h" // O_RDWR
+#include "utime.h" // utime
+#include <time.h> // asctime, clock, clock_t, etc.
+#include "errno.h" // EACCES
+
+
+#define _O_RDWR O_RDWR
+
+typedef struct stat _stat_;
+typedef struct utimbuf _utimbuf_;
+
+inline int _mkdir (const char* path)
+{
+#if PLATFORM_MAC
+ return mkdir (path);
+#else
+ return mkdir (path, 0777);
+#endif
+}
+
+inline int _rmdir (const char* path)
+{
+ return rmdir (path);
+}
+
+inline int _stat (const char * path, struct stat * buf)
+{
+ return stat (path, buf);
+}
+
+inline int _open (const char * path, int mode)
+{
+ return open (path, mode);
+}
+
+inline int _chsize (int s, off_t offset)
+{
+ return ftruncate (s, offset);
+}
+
+inline int _close (int s)
+{
+ return close (s);
+}
+
+inline int _utime (const char * path, const utimbuf * times)
+{
+ return utime (path, times);
+}
+
+#endif
+
+struct MyDIR
+{
+ EmDirRefList fDirs;
+ EmFileRefList fFiles;
+
+ EmDirRefList::iterator fDirIter;
+ EmFileRefList::iterator fFileIter;
+
+ int fState; // 0 = new, 1 = iterating dirs, 2 = iterating files, 3 = done
+};
+
+
+typedef void (*HostHandler) (void);
+
+static HostHandler PrvHostGetHandler (HostControlSelectorType selector);
+
+static Bool PrvCollectParameters (EmSubroutine& sub, const string& fmt,
+ ByteList& stackData, StringList& stringData);
+static void PrvPushShort (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushLong (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushDouble (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushLongDouble (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushString (EmSubroutine& sub, ByteList& stackData,
+ StringList& stringData);
+
+static FILE* PrvToFILE (emuptr);
+
+static void PrvTmFromHostTm (struct tm& dest, const HostTmType& src);
+static void PrvHostTmFromTm (EmProxyHostTmType& dest, const struct tm& src);
+
+static void PrvMapAndReturn (const void* p, long size, EmSubroutine& sub);
+static void PrvMapAndReturn (const string& s, EmSubroutine& sub);
+static void PrvReturnString (const char* p, EmSubroutine& sub);
+static void PrvReturnString (const string& s, EmSubroutine& sub);
+
+static void PrvReleaseAllResources (void);
+
+static emuptr PrvMalloc (long size);
+static emuptr PrvRealloc (emuptr p, long size);
+static void PrvFree (emuptr p);
+
+
+// Write to this "file" if you want to intertwine your
+// output with that created by any host logging facilities
+// (such as event logging).
+
+#define hostLogFile ((HostFILEType*) -1)
+#define hostLogFILE ((FILE*) -1)
+
+
+inline int x_fclose (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return 0;
+ }
+
+ return fclose (f);
+}
+
+inline int x_feof (FILE* f)
+{
+ return feof (f);
+}
+
+inline int x_ferror (FILE* f)
+{
+ return ferror (f);
+}
+
+inline int x_fflush (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ LogDump ();
+ return 0;
+ }
+
+ return fflush (f);
+}
+
+inline int x_fgetc (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return EOF;
+ }
+
+ return fgetc (f);
+}
+
+inline char* x_fgets (char* s, int n, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return NULL;
+ }
+
+ return fgets (s, n, f);
+}
+
+inline int x_vfprintf (FILE* f, const char* fmt, va_list args)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->VPrintf (fmt, args);
+ }
+
+ return vfprintf (f, fmt, args);
+}
+
+inline int x_fputc (int c, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->Printf ("%c", c);
+ }
+
+ return fputc (c, f);
+}
+
+inline int x_fputs (const char* s, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->Printf ("%s", s);
+ }
+
+ return fputs (s, f);
+}
+
+inline size_t x_fread (void* buffer, size_t size, size_t count, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return 0;
+ }
+
+ return fread (buffer, size, count, f);
+}
+
+inline int x_fseek (FILE* f, long offset, int origin)
+{
+ if (f == hostLogFILE)
+ {
+ return -1;
+ }
+
+ return fseek (f, offset, origin);
+}
+
+inline long x_ftell (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return -1;
+ }
+
+ return ftell (f);
+}
+
+inline size_t x_fwrite (const void* buffer, size_t size, size_t count, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->Write (buffer, size * count);
+ }
+
+ return fwrite (buffer, size, count, f);
+}
+
+static int translate_err_no (int err_no)
+{
+ switch (err_no)
+ {
+ case 0: return hostErrNone;
+ case EACCES:
+ case EPERM: return hostErrPermissions;
+ case ENOENT: return hostErrFileNotFound;
+ case EIO: return hostErrDiskError;
+ case EBADF: return hostErrInvalidParameter;
+ case ENOMEM: return hostErrOutOfMemory;
+ case EFAULT: return hostErrInvalidParameter;
+ case EEXIST: return hostErrExists;
+ case ENOTDIR: return hostErrNotADirectory;
+ case EISDIR: return hostErrIsDirectory;
+ case EINVAL: return hostErrInvalidParameter;
+ case ENFILE:
+ case EMFILE: return hostErrTooManyFiles;
+ case EFBIG: return hostErrFileTooBig;
+ case ENOSPC: return hostErrDiskFull;
+ case EROFS: return hostErrReadOnlyFS;
+ case ENAMETOOLONG: return hostErrFileNameTooLong;
+ case ENOTEMPTY: return hostErrDirNotEmpty;
+ case ENOSYS:
+ case ENODEV: return hostErrOpNotAvailable;
+ default: return hostErrUnknownError;
+ }
+}
+
+HostHandler gHandlerTable [hostSelectorLastTrapNumber];
+
+vector<FILE*> gOpenFiles;
+vector<MyDIR*> gOpenDirs;
+vector<void*> gAllocatedBlocks;
+HostDirEntType gHostDirEnt;
+string gResultString;
+EmProxyHostTmType gGMTime;
+EmProxyHostTmType gLocalTime;
+
+
+// ---------------------------------------------------------------------------
+// ¥ HandleHostControlCall
+// ---------------------------------------------------------------------------
+
+CallROMType HandleHostControlCall (void)
+{
+ CALLED_SETUP ("UInt4", "HostControlSelectorType selector");
+
+ CALLED_GET_PARAM_VAL (HostControlSelectorType, selector);
+
+ HostHandler fn = PrvHostGetHandler (selector);
+
+ if (fn)
+ {
+ fn ();
+ }
+ else
+ {
+ // !!! Display an "unknown function" error message.
+ }
+
+ return kSkipROM;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetHostVersion
+// ---------------------------------------------------------------------------
+
+static void _HostGetHostVersion (void)
+{
+ // long HostGetHostVersion (void)
+
+ CALLED_SETUP_HC ("Int32", "void");
+
+ enum { kMajor, kMinor, kFix, kBuild };
+
+ int major = 0;
+ int minor = 0;
+ int fix = 0;
+ int stage = sysROMStageRelease;
+ int buildNum = 0;
+ int state = kMajor;
+
+ string version (Platform::GetShortVersionString ());
+ string::iterator iter;
+
+ for (iter = version.begin (); iter != version.end (); ++iter)
+ {
+ char ch = *iter;
+
+ switch (state)
+ {
+ case kMajor:
+ if (isdigit (ch))
+ major = major * 10 + ch - '0';
+ else if (ch == '.')
+ state = kMinor;
+ else
+ goto VersionParseDone;
+ break;
+
+ case kMinor:
+ case kFix:
+ if (isdigit (ch))
+ {
+ if (state == kMinor)
+ minor = minor * 10 + ch - '0';
+ else
+ fix = fix * 10 + ch - '0';
+ }
+ else if (ch == '.')
+ {
+ if (state == kMinor)
+ state = kFix;
+ else
+ goto VersionParseDone;
+ }
+ else if (ch == 'd')
+ {
+ stage = sysROMStageDevelopment;
+ state = kBuild;
+ }
+ else if (ch == 'a')
+ {
+ stage = sysROMStageAlpha;
+ state = kBuild;
+ }
+ else if (ch == 'b')
+ {
+ stage = sysROMStageBeta;
+ state = kBuild;
+ }
+ else
+ goto VersionParseDone;
+ break;
+
+ case kBuild:
+ if (isdigit (ch))
+ buildNum = buildNum * 10 + ch - '0';
+ else
+ goto VersionParseDone;
+ break;
+ }
+ }
+
+VersionParseDone:
+
+ // Return the result.
+
+ Int32 result = sysMakeROMVersion (major, minor, fix, stage, buildNum);
+ PUT_RESULT_VAL (Int32, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetHostID
+// ---------------------------------------------------------------------------
+
+static void _HostGetHostID (void)
+{
+ // HostIDType HostGetHostID (void)
+
+ CALLED_SETUP_HC ("HostIDType", "void");
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostIDType, hostIDPalmOSEmulator);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetHostPlatform
+// ---------------------------------------------------------------------------
+
+static void _HostGetHostPlatform (void)
+{
+ // HostPlatformType HostGetHostPlatform (void)
+
+ CALLED_SETUP_HC ("HostPlatformType", "void");
+
+ // Return the result.
+
+#if PLATFORM_WINDOWS
+ PUT_RESULT_VAL (HostPlatformType, hostPlatformWindows);
+#elif PLATFORM_MAC
+ PUT_RESULT_VAL (HostPlatformType, hostPlatformMacintosh);
+#elif PLATFORM_UNIX
+ PUT_RESULT_VAL (HostPlatformType, hostPlatformUnix);
+#else
+ #error "Unsupported platform"
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostIsSelectorImplemented
+// ---------------------------------------------------------------------------
+
+static void _HostIsSelectorImplemented (void)
+{
+ // HostBoolType HostIsSelectorImplemented (long selector)
+
+ CALLED_SETUP_HC ("HostBoolType", "long selector");
+
+ CALLED_GET_PARAM_VAL (long, selector);
+
+ HostHandler fn = PrvHostGetHandler ((HostControlSelectorType) selector);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostBoolType, (fn != NULL));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGestalt
+// ---------------------------------------------------------------------------
+
+static void _HostGestalt (void)
+{
+ // HostErrType HostGestalt (long gestSel, long* response)
+
+ CALLED_SETUP_HC ("HostErrType", "long gestSel, long* response");
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrUnknownGestaltSelector);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostIsCallingTrap
+// ---------------------------------------------------------------------------
+
+static void _HostIsCallingTrap (void)
+{
+ // HostBoolType HostIsCallingTrap (void)
+
+ CALLED_SETUP_HC ("HostBoolType", "void");
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostBoolType, gSession->IsNested ());
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileInit
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileInit (void)
+{
+ // HostErrType HostProfileInit (long maxCalls, long maxDepth)
+
+ CALLED_SETUP_HC ("HostErrType", "long maxCalls, long maxDepth");
+
+ if (!::ProfileCanInit ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, maxCalls);
+ CALLED_GET_PARAM_VAL (long, maxDepth);
+
+ // Call the function.
+
+ ::ProfileInit (maxCalls, maxDepth);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileStart
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileStart (void)
+{
+ // HostErrType HostProfileStart (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ if (!::ProfileCanStart ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Call the function.
+
+ ::ProfileStart ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileStop
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileStop (void)
+{
+ // HostErrType HostProfileStop (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ if (!::ProfileCanStop ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Call the function.
+
+ ::ProfileStop ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileDump
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileDump (void)
+{
+ // HostErrType HostProfileDump (const char* filenameP)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* filenameP");
+
+ if (!::ProfileCanDump ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, filenameP);
+
+ // Call the function.
+
+ ::ProfileDump (filenameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileCleanup
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileCleanup (void)
+{
+ // HostErrType HostProfileCleanup (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ if (!::ProfileCanInit ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Get the caller's parameters.
+
+ // Call the function.
+
+ // ProfileCleanup is now performed at the end of a dump.
+// ::ProfileCleanup ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileDetailFn
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileDetailFn (void)
+{
+ // HostErrType _HostProfileDetailFn (void* addr, HostBoolType logDetails)
+
+ CALLED_SETUP_HC ("HostErrType", "void* addr, HostBoolType logDetails");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, addr);
+ CALLED_GET_PARAM_VAL (HostBoolType, logDetails);
+
+ // Call the function.
+
+ ProfileDetailFn (addr, logDetails);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileGetCycles
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileGetCycles (void)
+{
+ // long HostProfileGetCycles(void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ // Get the caller's parameters.
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, gClockCycles);
+}
+
+#endif
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostErrNo
+// ---------------------------------------------------------------------------
+
+static void _HostErrNo (void)
+{
+ // long HostErrNo (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ // Get the caller's parameters.
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, translate_err_no (errno));
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFClose
+// ---------------------------------------------------------------------------
+
+static void _HostFClose (void)
+{
+ // long HostFClose (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fclose (fh);
+
+ vector<FILE*>::iterator iter = gOpenFiles.begin ();
+ while (iter != gOpenFiles.end ())
+ {
+ if (*iter == fh)
+ {
+ gOpenFiles.erase (iter);
+ break;
+ }
+
+ ++iter;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFEOF
+// ---------------------------------------------------------------------------
+
+static void _HostFEOF (void)
+{
+ // long HostFEOF (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, 1); // At end of file (right choice?)
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_feof (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFError
+// ---------------------------------------------------------------------------
+
+static void _HostFError (void)
+{
+ // long HostFError (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_ferror (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, translate_err_no (result));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFFlush
+// ---------------------------------------------------------------------------
+
+static void _HostFFlush (void)
+{
+ // long HostFFlush (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fflush (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFGetC
+// ---------------------------------------------------------------------------
+
+static void _HostFGetC (void)
+{
+ // long HostFGetC (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF); // No file, no data...
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fgetc (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFGetPos
+// ---------------------------------------------------------------------------
+
+static void _HostFGetPos (void)
+{
+ // long HostFGetPos (HostFILEType* fileP, long* posP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP, long* posP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_REF (long, posP, Marshal::kInput);
+
+ // Check the parameters.
+
+ if (!fh || posP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, 1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ long pos = x_ftell (fh);
+
+ // If the function succeeded, return the position in
+ // the memory location pointed to by "posP".
+
+ if (pos >= 0) // success
+ {
+ *posP = pos;
+ CALLED_PUT_PARAM_REF (posP);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, (pos == -1 ? 1 : 0));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFGetS
+// ---------------------------------------------------------------------------
+
+static void _HostFGetS (void)
+{
+ // char* HostFGetS (char* s, long n, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("char*", "char* s, long n, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (uint32, n);
+ CALLED_GET_PARAM_PTR (char, s, n, Marshal::kOutput);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || s == EmMemNULL)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ emuptr returnVal = EmMemNULL;
+
+ if (n > 0)
+ {
+ char* result = x_fgets (s, (int) n, fh);
+
+ // If we were able to read the string, copy it into the
+ // user's buffer (using EmMem_strcpy to take care of real
+ // <-> emulated memory mapping. If the read failed,
+ // return NULL.
+
+ if (result != NULL)
+ {
+ CALLED_PUT_PARAM_REF (s);
+
+ returnVal = (emuptr) s;
+ }
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, returnVal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFOpen
+// ---------------------------------------------------------------------------
+
+static void _HostFOpen (void)
+{
+ // HostFILEType* HostFOpen (const char* name, const char* mode)
+
+ CALLED_SETUP_HC ("HostFILEType*", "const char* name, const char* mode");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, name);
+ CALLED_GET_PARAM_STR (char, mode);
+
+ // Check the parameters.
+
+ if (name == EmMemNULL || mode == EmMemNULL)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ FILE* result = fopen (name, mode);
+
+ if (result)
+ {
+ gOpenFiles.push_back (result);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFPrintF
+// ---------------------------------------------------------------------------
+
+static void _HostFPrintF (void)
+{
+ // long HostFPrintF (HostFILEType* fileP, const char* fmt, ...)
+
+ CALLED_SETUP_STDARG_HC ("long", "HostFILEType* fileP, const char* fmt");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_STR (char, fmt);
+
+ // Check the parameters.
+
+ if (!fh || fmt == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub, string (fmt), stackData, stringData))
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out to the file using vfprintf.
+
+ int result = x_vfprintf (fh, fmt, (va_list) &stackData[0]);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFPutC
+// ---------------------------------------------------------------------------
+
+static void _HostFPutC (void)
+{
+ // long HostFPutC (long c, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "long c, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, c);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fputc ((int) c, fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFPutS
+// ---------------------------------------------------------------------------
+
+static void _HostFPutS (void)
+{
+ // long HostFPutS (const char* s, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "const char* s, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, s);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || s == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fputs (s, fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFRead
+// ---------------------------------------------------------------------------
+
+static void _HostFRead (void)
+{
+ // long HostFRead (void* buffer, long size, long count, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "void* buffer, long size, long count, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, size);
+ CALLED_GET_PARAM_VAL (long, count);
+ CALLED_GET_PARAM_PTR (void, buffer, size * count, Marshal::kOutput);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || buffer == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, 0);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ size_t result = x_fread (buffer, size, count, fh);
+
+ // If the read succeeded, copy the data into the user's buffer.
+
+ if (result)
+ {
+ CALLED_PUT_PARAM_REF (buffer);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFReopen
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostFReopen (void)
+{
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFScanF
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostFScanF (void)
+{
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFSeek
+// ---------------------------------------------------------------------------
+
+static void _HostFSeek (void)
+{
+ // long HostFSeek (HostFILEType* fileP, long offset, long origin)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP, long offset, long origin");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_VAL (long, offset);
+ CALLED_GET_PARAM_VAL (long, origin);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, -1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fseek (fh, offset, (int) origin);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFSetPos
+// ---------------------------------------------------------------------------
+
+static void _HostFSetPos (void)
+{
+ // long HostFSetPos (HostFILEType* fileP, long* posP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP, long* posP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_REF (long, posP, Marshal::kInput);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, 1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fseek (fh, *posP, SEEK_SET);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFTell
+// ---------------------------------------------------------------------------
+
+static void _HostFTell (void)
+{
+ // long HostFTell (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, -1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ long result = x_ftell (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFWrite
+// ---------------------------------------------------------------------------
+
+static void _HostFWrite (void)
+{
+ // long HostFWrite (const void* buffer, long size, long count, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "const void* buffer, long size, long count, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, size);
+ CALLED_GET_PARAM_VAL (long, count);
+ CALLED_GET_PARAM_PTR (void, buffer, size * count, Marshal::kInput);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || buffer == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, 0);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ size_t result = x_fwrite (buffer, size, count, fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRemove
+// ---------------------------------------------------------------------------
+
+static void _HostRemove (void)
+{
+ // long HostRemove(const char* nameP)
+
+ CALLED_SETUP_HC ("long", "const char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Call the function.
+
+ int result = remove (nameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRename
+// ---------------------------------------------------------------------------
+
+static void _HostRename (void)
+{
+ // long HostRename(const char* oldNameP, const char* newNameP)
+
+ CALLED_SETUP_HC ("long", "const char* oldNameP, const char* newNameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, oldNameP);
+ CALLED_GET_PARAM_STR (char, newNameP);
+
+ // Call the function.
+
+ int result = rename (oldNameP, newNameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTmpFile
+// ---------------------------------------------------------------------------
+
+static void _HostTmpFile (void)
+{
+ // HostFILEType* HostTmpFile (void)
+
+ CALLED_SETUP_HC ("HostFILEType*", "void");
+
+ // Get the caller's parameters.
+
+ // Call the function.
+
+ FILE* result = tmpfile ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTmpNam
+// ---------------------------------------------------------------------------
+
+static void _HostTmpNam (void)
+{
+ // char* HostTmpNam (char* nameP)
+
+ CALLED_SETUP_HC ("char*", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_PTR (char, nameP, HOST_NAME_MAX, Marshal::kOutput);
+
+ // Check the parameters.
+
+ // Call the function.
+
+#if HAVE_MKSTEMP
+
+ // Try to find a good home for this file...
+
+ char* result = NULL;
+ char* env = NULL;
+ char temp_buff[HOST_NAME_MAX];
+
+ if (!env)
+ env = getenv ("TMPDIR");
+
+ if (!env)
+ env = getenv ("TEMP");
+
+#if defined (P_tmpdir)
+ if (!env)
+ env = P_tmpdir;
+#else
+ if (!env)
+ env = "/tmp";
+#endif
+
+ strcpy (temp_buff, env);
+ strcat (temp_buff, "/pose.XXXXXX");
+
+ // Create the temporary file name.
+
+ int fd = mkstemp (temp_buff);
+
+ // If that succeeded, close the file that was created
+ // and remember the file name.
+
+ if (fd > 0 && !close (fd))
+ {
+ result = temp_buff;
+
+ if (nameP != EmMemNULL)
+ {
+ strcpy ((char*) nameP, temp_buff);
+ }
+ }
+
+#else
+
+ char* result = tmpnam (nameP);
+
+#endif
+
+ // Return the result.
+
+ if (!result)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ }
+ else
+ {
+ if (nameP != EmMemNULL)
+ {
+ CALLED_PUT_PARAM_REF (nameP);
+ PUT_RESULT_VAL (emuptr, nameP);
+ }
+ else
+ {
+ ::PrvReturnString (result, sub);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetEnv
+// ---------------------------------------------------------------------------
+
+static void _HostGetEnv (void)
+{
+ // char* HostGetEnv (const char* nameP)
+
+ CALLED_SETUP_HC ("char*", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ char* value = getenv (nameP);
+
+ // Return the result.
+
+ ::PrvReturnString (value, sub);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostMalloc
+// ---------------------------------------------------------------------------
+
+static void _HostMalloc (void)
+{
+ // void* HostMalloc(long size)
+
+ CALLED_SETUP_HC ("void*", "long size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, size);
+
+ // Call the function.
+
+ emuptr result = ::PrvMalloc (size);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRealloc
+// ---------------------------------------------------------------------------
+
+static void _HostRealloc (void)
+{
+ // void* HostRealloc(void* p, long size)
+
+ CALLED_SETUP_HC ("void*", "void* p, long size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, p);
+ CALLED_GET_PARAM_VAL (long, size);
+
+ // Call the function.
+
+ emuptr result;
+
+ if (!p)
+ {
+ result = ::PrvMalloc (size);
+ }
+ else if (!size)
+ {
+ ::PrvFree (p);
+ result = EmMemNULL;
+ }
+ else
+ {
+ result = ::PrvRealloc (p, size);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFree
+// ---------------------------------------------------------------------------
+
+static void _HostFree (void)
+{
+ // void HostFree(void* p)
+
+ CALLED_SETUP_HC ("void", "void* p");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, p);
+
+ // Call the function.
+
+ ::PrvFree (p);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostAscTime
+// ---------------------------------------------------------------------------
+
+static void _HostAscTime (void)
+{
+ // char* HostAscTime(const HostTmType* hisTmP)
+
+ CALLED_SETUP_HC ("char*", "HostTmType* hisTmP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTmType, hisTmP, Marshal::kInput);
+
+ struct tm myTm;
+
+ ::PrvTmFromHostTm (myTm, *hisTmP);
+
+ // Call the function.
+
+ char* result = asctime (&myTm);
+
+ // Return the result.
+
+ ::PrvReturnString (result, sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostClock
+// ---------------------------------------------------------------------------
+
+static void _HostClock (void)
+{
+ // HostClockType HostClock(void)
+
+ CALLED_SETUP_HC ("HostClockType", "void");
+
+ // Get the caller's parameters.
+
+ // Call the function.
+
+ clock_t result = clock ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostClockType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostCTime
+// ---------------------------------------------------------------------------
+
+static void _HostCTime (void)
+{
+ // char* HostCTime(const HostTimeType*)
+
+ CALLED_SETUP_HC ("char*", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kInput);
+
+ time_t myTime = *timeP;
+
+ // Call the function.
+
+ char* result = ctime (&myTime);
+
+ // Return the result.
+
+ ::PrvReturnString (result, sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostDiffTime
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostDiffTime (void)
+{
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGMTime
+// ---------------------------------------------------------------------------
+
+static void _HostGMTime (void)
+{
+ // HostTmType* HostGMTime(const HostTimeType* timeP)
+
+ CALLED_SETUP_HC ("void*", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kInput);
+
+ time_t myTime = *timeP;
+
+ // Call the function.
+
+ struct tm* result = gmtime (&myTime);
+
+ ::PrvHostTmFromTm (gGMTime, *result);
+
+ // Return the result.
+
+ ::PrvMapAndReturn (&gGMTime, sizeof (gGMTime), sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostLocalTime
+// ---------------------------------------------------------------------------
+
+static void _HostLocalTime (void)
+{
+ // HostTmType* HostLocalTime(const HostTimeType* timeP)
+
+ CALLED_SETUP_HC ("HostTmType*", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kInput);
+
+ time_t myTime = *timeP;
+
+ // Call the function.
+
+ struct tm* result = localtime (&myTime);
+
+ ::PrvHostTmFromTm (gLocalTime, *result);
+
+ // Return the result.
+
+ ::PrvMapAndReturn (&gLocalTime, sizeof (gLocalTime), sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostMkTime
+// ---------------------------------------------------------------------------
+
+static void _HostMkTime (void)
+{
+ // HostTimeType HostMkTime(HostTmType* timeP)
+
+ CALLED_SETUP_HC ("HostTimeType", "HostTmType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTmType, timeP, Marshal::kInput);
+
+ struct tm myTm;
+
+ ::PrvTmFromHostTm (myTm, *timeP);
+
+ // Call the function.
+
+ time_t result = mktime (&myTm);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostTimeType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostStrFTime
+// ---------------------------------------------------------------------------
+
+static void _HostStrFTime (void)
+{
+ // HostSizeType HostStrFTime(char*, HostSizeType, const char*, const HostTmType*)
+
+ CALLED_SETUP_HC ("HostSizeType", "char* strDest, HostSizeType maxsize, const char* format,"
+ "const HostTmType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (HostSizeType, maxsize);
+ CALLED_GET_PARAM_PTR (char, strDest, maxsize, Marshal::kOutput);
+ CALLED_GET_PARAM_STR (char, format);
+ CALLED_GET_PARAM_REF (HostTmType, timeP, Marshal::kInput);
+
+ if (strDest == EmMemNULL || format == EmMemNULL || timeP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (HostSizeType, 0);
+ return;
+ }
+
+ struct tm myTime;
+
+ ::PrvTmFromHostTm (myTime, *timeP);
+
+ // Call the function.
+
+ size_t result = strftime (strDest, maxsize, format, &myTime);
+
+ CALLED_PUT_PARAM_REF (strDest);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostSizeType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTime
+// ---------------------------------------------------------------------------
+
+static void _HostTime (void)
+{
+ // HostTimeType HostTime(HostTimeType*)
+
+ CALLED_SETUP_HC ("HostTimeType", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kOutput);
+
+ // Call the function.
+
+ time_t result2;
+ time_t result = time (&result2);
+
+ if (timeP)
+ {
+ *timeP = result2;
+ CALLED_PUT_PARAM_REF (timeP);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostTimeType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostMkDir
+// ---------------------------------------------------------------------------
+
+static void _HostMkDir (void)
+{
+ // long HostMkDir (const char* nameP)
+
+ CALLED_SETUP_HC ("long", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Call the function.
+
+ int result = _mkdir (nameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRmDir
+// ---------------------------------------------------------------------------
+
+static void _HostRmDir (void)
+{
+ // long HostRmDir (const char* nameP)
+
+ CALLED_SETUP_HC ("long", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Call the function.
+
+ int result = _rmdir (nameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOpenDir
+// ---------------------------------------------------------------------------
+
+static void _HostOpenDir (void)
+{
+ // HostDIRType* HostOpenDir(const char*)
+
+ CALLED_SETUP_HC ("HostDIRType*", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // See if the directory exists.
+
+ EmDirRef dirRef (nameP);
+ if (!dirRef.Exists ())
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ return;
+ }
+
+ // Create a new MyDIR object to pass back as the HostDIRType.
+
+ MyDIR* dir = new MyDIR;
+ if (!dir)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ return;
+ }
+
+ // Initialize the MyDIR with the child entries.
+
+ dirRef.GetChildren (&dir->fFiles, &dir->fDirs);
+ dir->fState = 0;
+
+ // Remember this on our list of open directories and
+ // pass it back to the user.
+
+ gOpenDirs.push_back (dir);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, dir);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostReadDir
+// ---------------------------------------------------------------------------
+
+static void _HostReadDir(void)
+{
+ // HostDirEntType* HostReadDir(HostDIRType* dirP)
+
+ CALLED_SETUP_HC ("HostDIRType*", "HostDIRType* dirP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, dirP);
+
+ MyDIR* dir = (MyDIR*) (emuptr) dirP;
+
+ // Make sure dir is valid.
+
+ vector<MyDIR*>::iterator iter = gOpenDirs.begin ();
+ while (iter != gOpenDirs.end ())
+ {
+ // It appears to be on our list, so let's use it.
+ if (*iter == dir)
+ goto FoundIt;
+
+ ++iter;
+ }
+
+ // hostDir was not on our list. Return NULL.
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ return;
+
+FoundIt:
+
+ // Initialize our result in case of failure.
+
+ gHostDirEnt.d_name[0] = 0;
+
+ // Get the next dir or file, as the case may be.
+
+ switch (dir->fState)
+ {
+ // Just starting out. Initialize the directory iterator
+ // and fall through to the code that uses it.
+
+ case 0:
+ dir->fDirIter = dir->fDirs.begin ();
+ dir->fState = 1;
+ // Fall thru
+
+ // Iterating over directories; get the next one. If there
+ // are no more, start iterating over files.
+
+ case 1:
+ if (dir->fDirIter != dir->fDirs.end ())
+ {
+ strcpy (gHostDirEnt.d_name, dir->fDirIter->GetName().c_str());
+ ++dir->fDirIter;
+ break;
+ }
+
+ dir->fFileIter = dir->fFiles.begin ();
+ dir->fState = 2;
+ // Fall thru
+
+ // Iterating over files; get the next one. If there
+ // are no more, stop iterating.
+
+ case 2:
+ if (dir->fFileIter != dir->fFiles.end ())
+ {
+ strcpy (gHostDirEnt.d_name, dir->fFileIter->GetName().c_str());
+ ++dir->fFileIter;
+ break;
+ }
+ dir->fState = 3;
+
+ // No longer iterating. Just return NULL.
+
+ case 3:
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ break;
+ }
+
+ // If we're returning a value in gHostDirEnt, make
+ // sure it's mapped into emulated space.
+
+ if (gHostDirEnt.d_name[0] != 0)
+ {
+ emuptr result = EmBankMapped::GetEmulatedAddress (&gHostDirEnt);
+ if (result == EmMemNULL)
+ {
+ EmBankMapped::MapPhysicalMemory (&gHostDirEnt, sizeof (gHostDirEnt));
+ result = EmBankMapped::GetEmulatedAddress (&gHostDirEnt);
+ }
+
+ PUT_RESULT_VAL (emuptr, result);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostCloseDir
+// ---------------------------------------------------------------------------
+
+static void _HostCloseDir (void)
+{
+ // long HostCloseDir(HostDIRType*)
+
+ CALLED_SETUP_HC ("long", "HostDIRType* dirP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, dirP);
+
+ MyDIR* dir = (MyDIR*) (emuptr) dirP;
+
+ // Make sure dir is valid.
+
+ vector<MyDIR*>::iterator iter = gOpenDirs.begin ();
+ while (iter != gOpenDirs.end ())
+ {
+ if (*iter == dir)
+ {
+ // It's on our list. Remove it from the list and delete it.
+
+ gOpenDirs.erase (iter);
+ delete dir;
+ break;
+ }
+
+ ++iter;
+ }
+
+ // Unmap any mapped gHostDirEnt if we're not iterating over any
+ // other directories.
+
+ if (gOpenDirs.size () == 0)
+ {
+ EmBankMapped::UnmapPhysicalMemory (&gHostDirEnt);
+ }
+
+ // Return no error (should we return an error if DIR was not found?)
+
+ PUT_RESULT_VAL (long, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostStat
+// ---------------------------------------------------------------------------
+
+static void _HostStat(void)
+{
+ // long HostStat(const char*, HostStatType*)
+
+ CALLED_SETUP_HC ("long", "const char* nameP, HostStatType* statP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_REF (HostStatType, statP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL || statP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ _stat_ local_stat;
+ int result = _stat (nameP, &local_stat);
+
+ if (result == 0)
+ {
+ (*statP).st_dev_ = local_stat.st_dev;
+ (*statP).st_ino_ = local_stat.st_ino;
+ (*statP).st_mode_ = local_stat.st_mode;
+ (*statP).st_nlink_ = local_stat.st_nlink;
+ (*statP).st_uid_ = local_stat.st_uid;
+ (*statP).st_gid_ = local_stat.st_gid;
+ (*statP).st_rdev_ = local_stat.st_rdev;
+ (*statP).st_atime_ = local_stat.st_atime;
+ (*statP).st_mtime_ = local_stat.st_mtime;
+ (*statP).st_ctime_ = local_stat.st_ctime;
+ (*statP).st_size_ = local_stat.st_size;
+#if PLATFORM_WINDOWS
+ (*statP).st_blksize_ = 0;
+ (*statP).st_blocks_ = 0;
+ (*statP).st_flags_ = 0;
+#elif PLATFORM_MAC
+ (*statP).st_blksize_ = local_stat.st_blksize;
+ (*statP).st_blocks_ = local_stat.st_blocks;
+ (*statP).st_flags_ = local_stat.st_flags;
+#else
+ (*statP).st_blksize_ = local_stat.st_blksize;
+ (*statP).st_blocks_ = local_stat.st_blocks;
+ (*statP).st_flags_ = 0;
+#endif
+
+ CALLED_PUT_PARAM_REF (statP);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTruncate
+// ---------------------------------------------------------------------------
+
+static void _HostTruncate (void)
+{
+ // long HostTruncate(const char*, long)
+
+ CALLED_SETUP_HC ("long", "char* nameP, long size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_VAL (long, size);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL || size < 0)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ int result;
+
+ int fd = _open (nameP, _O_RDWR);
+ if (fd)
+ {
+ result = _chsize (fd, size);
+ _close (fd);
+ }
+ else
+ {
+ result = errno;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostUTime
+// ---------------------------------------------------------------------------
+
+static void _HostUTime (void)
+{
+ // long HostUTime (const char*, HostUTimeType*)
+
+ CALLED_SETUP_HC ("long", "char* nameP, HostUTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_REF (HostUTimeType, timeP, Marshal::kOutput);
+
+ if (nameP == EmMemNULL || timeP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, -1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ _utimbuf_ buf;
+ _utimbuf_* bufP = NULL;
+
+ if (timeP)
+ {
+// buf.crtime = (*timeP).crtime_;
+ buf.actime = (*timeP).actime_;
+ buf.modtime = (*timeP).modtime_;
+
+ bufP = &buf;
+ }
+
+ // Make the call
+
+ int result = _utime (nameP, bufP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetFileAttr
+// ---------------------------------------------------------------------------
+
+static void _HostGetFileAttr(void)
+{
+ // long HostGetFileAttr(const char*, unsigned long * attr)
+
+ CALLED_SETUP_HC ("long", "char* nameP, unsigned long * attrP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_REF (unsigned long, attrP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL || attrP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ EmFileRef fRef (nameP);
+
+ int attr = 0;
+ errno = fRef.GetAttr (&attr);
+
+ // Return the result.
+
+ if (errno != 0)
+ {
+ PUT_RESULT_VAL (long, -1);
+ return;
+ }
+
+ *attrP = attr;
+ CALLED_PUT_PARAM_REF (attrP);
+
+ PUT_RESULT_VAL (long, hostErrNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSetFileAttr
+// ---------------------------------------------------------------------------
+
+static void _HostSetFileAttr(void)
+{
+ // long HostSetFileAttr(const char*, unsigned long attr)
+
+ CALLED_SETUP_HC ("long", "char* nameP, unsigned long attr");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_VAL (unsigned long, attr);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ EmFileRef fRef(nameP);
+
+ errno = fRef.SetAttr(attr);
+
+ // Return the result.
+
+ if (errno != 0)
+ {
+ PUT_RESULT_VAL (long, -1);
+ return;
+ }
+
+ PUT_RESULT_VAL (long, hostErrNone);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinIsRunning
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinIsRunning (void)
+{
+ // HostBoolType HostGremlinIsRunning (void)
+
+ CALLED_SETUP_HC ("HostBoolType", "void");
+
+ PUT_RESULT_VAL (HostBoolType, (Hordes::IsOn () ? 1 : 0));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinNumber
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinNumber (void)
+{
+ // long HostGremlinNumber (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ PUT_RESULT_VAL (long, Hordes::GremlinNumber ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinCounter
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinCounter (void)
+{
+ // long HostGremlinCounter (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ PUT_RESULT_VAL (long, Hordes::EventCounter ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinLimit
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinLimit (void)
+{
+ // long HostGremlinLimit (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ PUT_RESULT_VAL (long, Hordes::EventLimit ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinNew
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinNew (void)
+{
+ // HostErrType HostGremlinNew (const HostGremlinInfoType*)
+
+ CALLED_SETUP_HC ("HostErrType", "const HostGremlinInfoType* infoP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostGremlinInfoType, infoP, Marshal::kInput);
+
+ // Get the easy parts.
+
+ HordeInfo info;
+
+ info.fStartNumber = (*infoP).fFirstGremlin;
+ info.fStopNumber = (*infoP).fLastGremlin;
+ info.fSaveFrequency = (*infoP).fSaveFrequency;
+ info.fSwitchDepth = (*infoP).fSwitchDepth;
+ info.fMaxDepth = (*infoP).fMaxDepth;
+
+ info.OldToNew (); // Transfer the old fields to the new fields.
+
+ // Get the list of installed applications so that we can compare it to
+ // the list of applications requested by the caller.
+
+ DatabaseInfoList installedAppList;
+ ::GetDatabases (installedAppList, kApplicationsOnly);
+
+ // Get the list of applications requested by the caller. Break up the
+ // string into a list of individual names, and check to see if the whole
+ // thing was preceded by a '-'.
+
+ string appNames ((*infoP).fAppNames);
+
+ Bool exclude = false;
+ if (appNames[0] == '-')
+ {
+ exclude = true;
+ appNames = appNames.substr(1);
+ }
+
+ StringList requestedAppList;
+ ::SeparateList (requestedAppList, appNames, ',');
+
+ // For each requested application, see if it's installed in the device.
+ // If so, add it to the list of applications Gremlins should be run on.
+
+ StringList::iterator iter1 = requestedAppList.begin();
+ while (iter1 != requestedAppList.end())
+ {
+ // Get the application info based on the given name.
+
+ DatabaseInfoList::iterator iter2 = installedAppList.begin ();
+ while (iter2 != installedAppList.end ())
+ {
+ Bool addIt;
+
+ if (exclude)
+ addIt = *iter1 != iter2->name;
+ else
+ addIt = *iter1 == iter2->name;
+
+ if (addIt)
+ {
+ info.fAppList.push_back (*iter2);
+ }
+
+ ++iter2;
+ }
+
+ ++iter1;
+ }
+
+ // Start up the gremlin sub-system.
+
+ EmAssert (gDocument);
+ gDocument->ScheduleNewHorde (info);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostImportFile
+// ---------------------------------------------------------------------------
+
+static void _HostImportFile (void)
+{
+ // HostErrType HostImportFile (const char* fileName, long cardNum)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* fileName, long cardNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileName);
+// CALLED_GET_PARAM_VAL (long, cardNum);
+
+ // Check the parameters.
+
+ if (fileName == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ try
+ {
+ EmFileRef fileRef (fileName);
+ EmFileRefList fileList;
+ fileList.push_back (fileRef);
+
+ vector<LocalID> idList;
+ EmFileImport::LoadPalmFileList (fileList, kMethodBest, idList);
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostImportFileWithID
+// ---------------------------------------------------------------------------
+
+static void _HostImportFileWithID (void)
+{
+ // HostErrType HostImportFileWithID (const char* fileName, long cardNum, LocalID *newIDP)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* fileName, long cardNum, LocalID *newIDP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileName);
+// CALLED_GET_PARAM_VAL (long, cardNum);
+ CALLED_GET_PARAM_REF (LocalID, newIDP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ if (fileName == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ *newIDP = 0;
+
+ try
+ {
+ EmFileRef fileRef (fileName);
+ EmFileRefList fileList;
+ fileList.push_back (fileRef);
+
+ vector<LocalID> idList;
+ EmFileImport::LoadPalmFileList (fileList, kMethodBest, idList);
+
+ EmAssert (idList.size () == fileList.size ());
+
+ *newIDP = idList.front ();
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ CALLED_PUT_PARAM_REF(newIDP);
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExportFile
+// ---------------------------------------------------------------------------
+
+static void _HostExportFile (void)
+{
+ // HostErrType HostExportFile (const char* dbNameP, long cardNum, const char* fileNameP)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* fileName, long cardNum, const char* dbName");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileName);
+ CALLED_GET_PARAM_VAL (long, cardNum);
+ CALLED_GET_PARAM_STR (char, dbName);
+
+ // Check the parameters.
+
+ if (fileName == NULL || dbName == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ try
+ {
+ EmFileRef ref (fileName);
+ EmStreamFile stream (ref, kCreateOrEraseForUpdate,
+ kFileCreatorInstaller, kFileTypePalmApp);
+ ::SavePalmFile (stream, cardNum, dbName);
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSaveScreen
+// ---------------------------------------------------------------------------
+
+static void _HostSaveScreen (void)
+{
+ // HostErrType HostSaveScreen (const char* fileNameP)
+
+ CALLED_SETUP_HC ("HostErrType", "char* fileNameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileNameP);
+
+ // Check the parameters.
+
+ if (fileNameP == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ try
+ {
+ EmFileRef ref (fileNameP);
+
+ EmAssert (gDocument);
+ gDocument->HostSaveScreen (ref);
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+#pragma mark -
+
+#define exgErrBadData (exgErrorClass | 8) // internal data was not valid
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibOpen
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibOpen (void)
+{
+ // Err ExgLibOpen (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibOpen (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibClose
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibClose (void)
+{
+ // Err ExgLibClose (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibClose (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibSleep
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibSleep (void)
+{
+ // Err ExgLibSleep (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibSleep (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibWake
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibWake (void)
+{
+ // Err ExgLibWake (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibWake (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibHandleEvent
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibHandleEvent (void)
+{
+ // Boolean ExgLibHandleEvent (UInt16 libRefNum, void* eventP)
+
+ CALLED_SETUP_HC ("Boolean", "UInt16 libRefNum, void* eventP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, eventP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Boolean result = exgMgr->ExgLibHandleEvent (libRefNum, eventP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Boolean, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibConnect
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibConnect (void)
+{
+ // Err ExgLibConnect (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibConnect (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibAccept
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibAccept (void)
+{
+ // Err ExgLibAccept (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibAccept (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibDisconnect
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibDisconnect (void)
+{
+ // Err ExgLibDisconnect (UInt16 libRefNum, void* exgSocketP, Err error)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP, Err error");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+ CALLED_GET_PARAM_VAL (Err, error);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibDisconnect (libRefNum, exgSocketP, error);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibPut
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibPut (void)
+{
+ // Err ExgLibPut (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibPut (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibGet
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibGet (void)
+{
+ // Err ExgLibGet (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibGet (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibSend
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibSend (void)
+{
+ // UInt32 ExgLibSend (UInt16 libRefNum, void* exgSocketP,
+ // const void* const bufP, const UInt32 bufLen, Err* errP)
+
+ CALLED_SETUP_HC ("UInt32", "UInt16 libRefNum, void* exgSocketP,"
+ "const void* const bufP, const UInt32 bufLen, Err* errP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+ CALLED_GET_PARAM_VAL (UInt32, bufLen);
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ *errP = exgErrBadData;
+ PUT_RESULT_VAL (UInt32, 0);
+ return;
+ }
+
+ // Make the call
+
+ UInt32 result = exgMgr->ExgLibSend (libRefNum, exgSocketP, bufP, bufLen, errP);
+
+ // Return the result.
+
+ CALLED_PUT_PARAM_REF (errP);
+
+ PUT_RESULT_VAL (UInt32, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibReceive
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibReceive (void)
+{
+ // UInt32 ExgLibReceive (UInt16 libRefNum, void* exgSocketP,
+ // void* bufP, const UInt32 bufLen, Err* errP)
+
+ CALLED_SETUP_HC ("UInt32", "UInt16 libRefNum, void* exgSocketP,"
+ "const void* const bufP, const UInt32 bufLen, Err* errP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+ CALLED_GET_PARAM_VAL (UInt32, bufLen);
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ *errP = exgErrBadData;
+ PUT_RESULT_VAL (UInt32, 0);
+ return;
+ }
+
+ // Make the call
+
+ UInt32 result = exgMgr->ExgLibReceive (libRefNum, exgSocketP, bufP, bufLen, errP);
+
+ // Return the result.
+
+ CALLED_PUT_PARAM_REF (bufP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ PUT_RESULT_VAL (UInt32, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibControl
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibControl (void)
+{
+ // Err ExgLibControl (UInt16 libRefNum, UInt16 op,
+ // void* valueP, UInt16* valueLenP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, UInt16 op, void* valueP, UInt16* valueLenP");
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (UInt16, op);
+ CALLED_GET_PARAM_VAL (emuptr, valueP);
+ CALLED_GET_PARAM_VAL (emuptr, valueLenP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibControl (libRefNum, op, valueP, valueLenP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibRequest
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibRequest (void)
+{
+ // Err ExgLibRequest (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibRequest (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetPreference
+// ---------------------------------------------------------------------------
+
+static void _HostGetPreference (void)
+{
+ // HostBoolType HostGetPreference (const char* key, char* value);
+
+ CALLED_SETUP_HC ("HostBoolType", "const char* key, char* value");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, key);
+ CALLED_GET_PARAM_VAL (emuptr, value);
+
+ string keyStr ((const char*) key);
+
+ if (keyStr == "ReportIntlStrictChecks")
+ {
+ keyStr = "ReportStrictIntlChecks";
+ }
+
+ Preference<string> pref (keyStr.c_str ());
+
+ PUT_RESULT_VAL (HostBoolType, 0);
+
+ if (pref.Loaded ())
+ {
+ EmMem_strcpy ((emuptr) value, pref->c_str ());
+ PUT_RESULT_VAL (HostBoolType, 1);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSet1Preference
+// ---------------------------------------------------------------------------
+
+static void _HostSetPreference (void)
+{
+ // void HostSetPreference (const char*, const char*);
+
+ CALLED_SETUP_HC ("HostBoolType", "const char* key, char* value");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, key);
+ CALLED_GET_PARAM_STR (char, value);
+
+ string keyStr ((const char*) key);
+
+ if (keyStr == "ReportIntlStrictChecks")
+ {
+ keyStr = "ReportStrictIntlChecks";
+ }
+
+ Preference<string> pref (keyStr.c_str ());
+ pref = string (value);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostLogFile
+// ---------------------------------------------------------------------------
+
+static void _HostLogFile (void)
+{
+ // HostFILEType* HostLogFile (void)
+
+ CALLED_SETUP_HC ("HostFILEType", "void");
+
+ PUT_RESULT_VAL (emuptr, hostLogFile);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSetLogFileSize
+// ---------------------------------------------------------------------------
+
+static void _HostSetLogFileSize (void)
+{
+ // void HostSetLogFileSize (long newSize)
+
+ CALLED_SETUP_HC ("void", "long newSize");
+
+ CALLED_GET_PARAM_VAL (long, newSize);
+
+ Preference<long> logFileSize (kPrefKeyLogFileSize);
+ logFileSize = (long) newSize;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionCreate
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostSessionCreate (void)
+{
+ // HostErrType HostSessionCreate(const char* device, long ramSize, const char* romPath)
+
+ struct StackFrame
+ {
+ const char* device;
+ long ramSize;
+ const char* romPath;
+ };
+
+ string deviceStr = ToString (GET_PARAMETER (device));
+ RAMSizeType ramSize = GET_PARAMETER (ramSize);
+ string romPathStr = ToString (GET_PARAMETER (romPath));
+
+ // See if it's OK to create a session.
+
+ if (Platform::SessionRunning())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrSessionNotRunning);
+ return;
+ }
+
+ // Convert the device string into a DeviceType
+
+ DeviceType device = kDeviceUnspecified;
+ EmDeviceMenuItemList devices = EmDevice::GetMenuItemList ();
+ EmDeviceMenuItemList::iterator deviceIter = devices.begin();
+
+ while (deviceIter != devices.end())
+ {
+ if (_stricmp (deviceStr.c_str(), deviceIter->second.c_str()) == 0)
+ {
+ device = deviceIter->first;
+ break;
+ }
+ }
+
+ if (device == kDeviceUnspecified)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidDeviceType);
+ return;
+ }
+
+ // Validate the RAM size
+
+ Bool sizeOK = false;
+ MemoryTextList sizes;
+ ::GetMemoryTextList (sizes);
+
+ MemoryTextList::iterator sizeIter = sizes.begin();
+ while (sizeIter != sizes.end())
+ {
+ if (ramSize == sizeIter->first)
+ {
+ sizeOK = true;
+ break;
+ }
+ }
+
+ if (!sizeOK)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidRAMSize);
+ return;
+ }
+
+ // Convert the ROM file string into a EmFileRef.
+
+ EmFileRef romRef(romPathStr);
+ if (!romRef.Exists())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrFileNotFound);
+ return;
+ }
+
+ // Kick this all off.
+
+ Configuration cfg (device, ramSize, romRef);
+ EmAssert (gApplication);
+ gApplication->ScheduleCreateSession (cfg);
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionOpen
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostSessionOpen (void)
+{
+ // HostErrType HostSessionOpen (const char* psfFileName);
+
+ struct StackFrame
+ {
+ const char* psfFileName;
+ };
+
+ string psfFileName = ToString (GET_PARAMETER (psfFileName));
+
+ // See if it's OK to open a session.
+
+ if (Platform::SessionRunning())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrSessionNotRunning);
+ return;
+ }
+
+ // Validate the file to open.
+
+ EmFileRef psfFileRef(psfFileName);
+ if (!psfFileRef.Exists())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrFileNotFound);
+ return;
+ }
+
+ // Kick this all off.
+
+ EmAssert (gApplication);
+ gApplication->ScheduleOpenSession (psfFileRef);
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionSave
+// ---------------------------------------------------------------------------
+
+static void _HostSessionSave (void)
+{
+ // HostBoolType HostSessionSave (const char* saveFileName)
+
+ CALLED_SETUP_HC ("HostBoolType", "const char* saveFileName");
+
+ CALLED_GET_PARAM_STR (char, saveFileName);
+
+ // See if it's OK to close a session.
+
+ if (!gSession)
+ {
+ // !!! Oops. Returning an error code as a Boolean...
+ PUT_RESULT_VAL (HostBoolType, hostErrSessionNotRunning);
+ return;
+ }
+
+ EmFileRef saveFileRef (saveFileName);
+
+ // Saving will save the PC at the current instruction, which saves the state.
+ // Upon resumption, the current instruction will cause a save again. This
+ // will repeat infinitely. So advance the PC to the following instruction
+ // before saving.
+
+ // First, get the address of the function that got us here.
+ // If the system call is being made by a TRAP $F, the PC has already
+ // been bumped past the opcode. If being made with a JSR via the
+ // SYS_TRAP_FAST macro, the PC has not been adjusted.
+ //
+ // !!! Note that the following is 68K-specific!
+
+ emuptr startPC = gCPU->GetPC ();
+ if ((EmMemGet16 (startPC) & 0xF000) == 0xA000)
+ {
+ startPC -= 2; // Back us up to the TRAP $F
+ }
+
+ SystemCallContext context;
+ if (GetSystemCallContext (startPC, context))
+ {
+ gCPU->SetPC (context.fNextPC);
+
+ // Set the return value to something else so that the code that is restored can distinguish
+ // the saved case from not saved case.
+
+ PUT_RESULT_VAL (HostBoolType, true);
+
+ gSession->Save (saveFileRef, false);
+ }
+
+ PUT_RESULT_VAL (HostBoolType, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionClose
+// ---------------------------------------------------------------------------
+
+static void _HostSessionClose (void)
+{
+ // HostErrType HostSessionClose (const char* saveFileName)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* saveFileName");
+
+ CALLED_GET_PARAM_STR (char, saveFileName);
+
+ // See if it's OK to close a session.
+
+ if (!gSession)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrSessionNotRunning);
+ return;
+ }
+
+ EmFileRef saveFileRef(saveFileName);
+
+ // Kick this all off.
+
+ gApplication->ScheduleSessionClose (saveFileRef);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionQuit
+// ---------------------------------------------------------------------------
+
+static void _HostSessionQuit (void)
+{
+ // HostErrType HostSessionQuit (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ // See if it's OK to quit Poser.
+
+ if (gSession)
+ {
+// PUT_RESULT_VAL (HostErrType, hostErrSessionRunning);
+// return;
+ }
+
+ // Kick this all off.
+
+ gApplication->ScheduleQuit ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSignalSend
+// ---------------------------------------------------------------------------
+// Called by anyone wanting to send a signal to any waiting scripts.
+
+static void _HostSignalSend (void)
+{
+ // HostErrType HostSignalSend (HostSignalType signalNumber)
+
+ CALLED_SETUP_HC ("HostErrType", "HostSignalType signalNumber");
+
+ CALLED_GET_PARAM_VAL (HostSignalType, signalNumber);
+
+ RPC::SignalWaiters (signalNumber);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSignalWait
+// ---------------------------------------------------------------------------
+// Called by scripts that want to get a signal sent from HostSignalSend.
+
+static void _HostSignalWait (void)
+{
+ // HostErrType HostSignalWait (long timeout)
+
+ CALLED_SETUP_HC ("HostErrType", "long timeout");
+
+ CALLED_GET_PARAM_VAL (long, timeout);
+
+ // Unblock the CPU thread if it's suspended from a previous
+ // HostSignalSend call.
+
+ EmAssert (gSession);
+ gSession->ScheduleResumeExternal ();
+
+ if (RPC::HandlingPacket ())
+ {
+ RPC::DeferCurrentPacket (timeout);
+
+ if (EmPatchState::UIInitialized ())
+ {
+ ::EvtWakeup (); // Wake up the process in case the caller is looking
+ // for an idle event (which would never otherwise
+ // happen if EvtGetEvent has already been called and
+ // is blocking).
+ }
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSignalResume
+// ---------------------------------------------------------------------------
+// Called by scripts to restart the emulator after it has sent a signal and
+// then suspended itself.
+
+static void _HostSignalResume (void)
+{
+ // HostErrType HostSignalResume (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ EmAssert (gSession);
+ gSession->ScheduleResumeExternal ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+#pragma mark -
+
+#if HAS_TRACER
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceInit
+// ---------------------------------------------------------------------------
+
+static void _HostTraceInit (void)
+{
+ gTracer.InitOutputPort ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceClose
+// ---------------------------------------------------------------------------
+
+static void _HostTraceClose (void)
+{
+ gTracer.CloseOutputPort ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceOutputT
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputT (void)
+{
+ // void HostTraceOutputT (unsigned short, const char*, ...)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVT( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceOutputTL
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputTL (void)
+{
+ // void HostTraceOutputTL (unsigned short, const char*, ...)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVTL( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOutputVT
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputVT (void)
+{
+ // void HostTraceOutputVT (unsigned short module, const char* fmt, char* va_addr)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt, const char* va_addr");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+ CALLED_GET_PARAM_VAL (emuptr, va_addr);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // We get the parameters from va_addr, not the stack, so create a new
+ // EmSubroutine object to access them.
+
+ EmSubroutine sub2;
+ sub2.PrepareStack (va_addr);
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub2, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVT( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOutputVTL
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputVTL (void)
+{
+ // void HostTraceOutputVTL (unsigned short module, const char* fmt, char* va_addr)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt, const char* va_addr");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+ CALLED_GET_PARAM_VAL (emuptr, va_addr);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // We get the parameters from va_addr, not the stack, so create a new
+ // EmSubroutine object to access them.
+
+ EmSubroutine sub2;
+ sub2.PrepareStack (va_addr);
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub2, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVTL( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOutputB
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputB (void)
+{
+ // void HostTraceOutputB (unsigned short, const void*, HostSizeType)
+
+ CALLED_SETUP_HC ("void", "UInt16 module, const void* buf, HostSizeType length");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_VAL (HostSizeType, length);
+ CALLED_GET_PARAM_PTR (void, buf, length, Marshal::kInput);
+
+ // Check the parameters.
+
+ if (buf == NULL || length == 0)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ gTracer.OutputB (module, buf, length);
+}
+
+#endif // HAS_TRACER
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostDbgSetDataBreak
+// ---------------------------------------------------------------------------
+
+static void _HostDbgSetDataBreak (void)
+{
+ // HostErr HostDbgSetDataBreak (UInt32 addr, UInt32 size)
+
+ CALLED_SETUP_HC ("HostErr", "UInt32 addr, UInt32 size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt32, addr);
+ CALLED_GET_PARAM_VAL (UInt32, size);
+
+ // Check the parameters.
+
+ if (!addr || !size)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Set data breakpoint.
+
+ gDebuggerGlobals.watchEnabled = true;
+
+ if (gDebuggerGlobals.watchEnabled)
+ {
+ gDebuggerGlobals.watchAddr = addr;
+ gDebuggerGlobals.watchBytes = size;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostDbgClearDataBreak
+// ---------------------------------------------------------------------------
+
+static void _HostDbgClearDataBreak (void)
+{
+ // HostErr HostDbgClearDataBreak (void)
+
+ CALLED_SETUP_HC ("HostErr", "void");
+
+ // Get the caller's parameters.
+
+ // Check the parameters.
+
+ // Set data breakpoint
+
+ gDebuggerGlobals.watchEnabled = false;
+
+ if (!gDebuggerGlobals.watchEnabled)
+ {
+ gDebuggerGlobals.watchAddr = 0;
+ gDebuggerGlobals.watchBytes = 0;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSlotMax
+// ---------------------------------------------------------------------------
+
+static void _HostSlotMax (void)
+{
+ // long HostSlotMax(void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ int maxSlotNo = 0;
+
+ Preference<SlotInfoList> slots (kPrefKeySlotList);
+
+ SlotInfoList::const_iterator iter = (*slots).begin ();
+ while (iter != (*slots).end ())
+ {
+ if (maxSlotNo < iter->fSlotNumber)
+ {
+ maxSlotNo = iter->fSlotNumber;
+ }
+
+ ++iter;
+ }
+
+ PUT_RESULT_VAL (long, maxSlotNo);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSlotRoot
+// ---------------------------------------------------------------------------
+
+static void _HostSlotRoot (void)
+{
+ // const char* HostSlotRoot(long slotNo)
+
+ CALLED_SETUP_HC ("char*", "long slotNo");
+
+ CALLED_GET_PARAM_VAL (long, slotNo);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ Preference<SlotInfoList> slots (kPrefKeySlotList);
+
+ SlotInfoList::const_iterator iter = (*slots).begin ();
+ while (iter != (*slots).end ())
+ {
+ if (slotNo == iter->fSlotNumber)
+ {
+ if (iter->fSlotOccupied)
+ {
+ ::PrvReturnString (iter->fSlotRoot.GetFullPath (), sub);
+ }
+
+ break;
+ }
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSlotHasCard
+// ---------------------------------------------------------------------------
+
+static void _HostSlotHasCard (void)
+{
+ // HostBoolType HostSlotHasCard(long slotNo)
+
+ CALLED_SETUP_HC ("HostBoolType", "long slotNo");
+
+ CALLED_GET_PARAM_VAL (long, slotNo);
+
+ PUT_RESULT_VAL (HostBoolType, false);
+
+ Preference<SlotInfoList> slots (kPrefKeySlotList);
+
+ SlotInfoList::const_iterator iter = (*slots).begin ();
+ while (iter != (*slots).end ())
+ {
+ if (slotNo == iter->fSlotNumber)
+ {
+ PUT_RESULT_VAL (HostBoolType, iter->fSlotOccupied);
+ break;
+ }
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetFile
+// ---------------------------------------------------------------------------
+
+static void _HostGetFile (void)
+{
+ // const char* HostGetFile(const char* prompt, const char* defaultDirName)
+
+ CALLED_SETUP_HC ("char*", "const char* prompt, const char* defaultDirName");
+
+ CALLED_GET_PARAM_STR (char, prompt);
+ CALLED_GET_PARAM_STR (char, defaultDirName);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ EmDirRef defaultDir (defaultDirName);
+
+ EmFileRef result;
+ EmFileTypeList filterList (1, kFileTypeAll);
+
+ if (EmDlg::DoGetFile (result, string (prompt), defaultDir, filterList) == kDlgItemOK)
+ {
+ ::PrvReturnString (result.GetFullPath (), sub);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostPutFile
+// ---------------------------------------------------------------------------
+
+static void _HostPutFile (void)
+{
+ // const char* HostPutFile(const char* prompt, const char* defaultDirName, const char* defaultName)
+
+ CALLED_SETUP_HC ("char*", "const char* prompt, const char* defaultDirName, const char* defaultName");
+
+ CALLED_GET_PARAM_STR (char, prompt);
+ CALLED_GET_PARAM_STR (char, defaultDirName);
+ CALLED_GET_PARAM_STR (char, defaultName);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ EmDirRef defaultDir (defaultDirName);
+
+ EmFileRef result;
+ EmFileTypeList filterList (1, kFileTypeAll);
+
+ if (EmDlg::DoPutFile (result, string (prompt), defaultDir,
+ filterList, string (defaultName)) == kDlgItemOK)
+ {
+ ::PrvReturnString (result.GetFullPath (), sub);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetDirectory
+// ---------------------------------------------------------------------------
+
+static void _HostGetDirectory (void)
+{
+ // const char* HostGetDirectory(const char* prompt, const char* defaultDirName)
+
+ CALLED_SETUP_HC ("char*", "const char* prompt, const char* defaultDirName");
+
+ CALLED_GET_PARAM_STR (char, prompt);
+ CALLED_GET_PARAM_STR (char, defaultDirName);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ EmDirRef defaultDir (defaultDirName);
+
+ EmDirRef result;
+
+ if (EmDlg::DoGetDirectory (result, string (prompt), defaultDir) == kDlgItemOK)
+ {
+ ::PrvReturnString (result.GetFullPath (), sub);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ PrvHostGetHandler
+// ---------------------------------------------------------------------------
+
+HostHandler PrvHostGetHandler (HostControlSelectorType selector)
+{
+ HostHandler fn = NULL;
+
+ // Hack for GremlinIsOn; see comments at head of HostTraps.h.
+
+ if ((selector & 0xFF00) == 0)
+ {
+ selector = hostSelectorGremlinIsRunning;
+ }
+
+ if (selector < hostSelectorLastTrapNumber)
+ {
+ fn = gHandlerTable [selector];
+ }
+
+ return fn;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCollectParameters
+// ---------------------------------------------------------------------------
+
+Bool PrvCollectParameters (EmSubroutine& sub, const string& fmt, ByteList& stackData, StringList& stringData)
+{
+ // Start parsing up the format string.
+
+ string::const_iterator iter;
+
+ for (iter = fmt.begin (); iter != fmt.end ();)
+ {
+ char ch = *iter++;
+
+ /*
+ Format specification:
+
+ % ? 12 .4 h d
+ | | | | | |
+ | | | | | +-- conversion letter
+ | | | | +---- size modifier (l, L, or h)
+ | | | +------ precision
+ | | +--------- minimum width field
+ | +------------ flags (one or more of +, -, #, 0, or space)
+ +-------------- start of specification
+ */
+
+ if (ch == '%')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+
+ // Skip over any flags.
+
+ while (ch == '+' || ch == '-' || ch == ' ' || ch == '#' || ch == '0')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+
+ // Skip over any minimum width field.
+
+ if (ch == '*')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+ else
+ {
+ while (ch >= '0' && ch <= '9')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+ }
+
+ // Skip over any precision.
+
+ if (ch == '.')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+
+ while (ch >= '0' && ch <= '9')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+ }
+
+ // Get any size modifier.
+
+ enum { kSizeNone, kSizeLongInt, kSizeLongDouble, kSizeShortInt };
+
+ int mod = kSizeNone;
+
+ if (ch == 'l')
+ mod = kSizeLongInt;
+ else if (ch == 'L')
+ mod = kSizeLongDouble;
+ else if (ch == 'h')
+ mod = kSizeShortInt;
+
+ // If there was a modifier, it's been handled,
+ // so skip over it.
+
+ if (mod != kSizeNone)
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+
+ switch (ch)
+ {
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ // int, short, or long
+ if (mod == kSizeNone || mod == kSizeShortInt)
+ PrvPushShort (sub, stackData);
+ else
+ PrvPushLong (sub, stackData);
+ break;
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ // double or long double
+ if (mod == kSizeNone)
+ PrvPushDouble (sub, stackData);
+ else
+ PrvPushLongDouble (sub, stackData);
+ break;
+
+ case 'c':
+ // int or wint_t
+ if (mod == kSizeNone)
+ PrvPushShort (sub, stackData);
+#if defined (_MSC_VER)
+ else if (sizeof (wint_t) == 2)
+ PrvPushShort (sub, stackData);
+#endif
+ else
+ PrvPushLong (sub, stackData);
+ break;
+
+ case 's':
+ PrvPushString (sub, stackData, stringData);
+ break;
+
+ case 'p':
+ PrvPushLong (sub, stackData);
+ break;
+
+ case 'n':
+ // pointer
+ // !!! Not supported for now...
+ return false;
+
+ case '%':
+ // none
+ break;
+
+ default:
+ // Bad conversion...
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushShort
+// ---------------------------------------------------------------------------
+
+void PrvPushShort (EmSubroutine& sub, ByteList& stackData)
+{
+ // Read a 2-byte int from the caller's stack, and push it
+ // onto our stack as a 4-byte int.
+
+ char paramName[20];
+ sprintf (paramName, "param%d", (int) stackData.size ());
+
+ char decl[20];
+ sprintf (decl, "UInt16 %s", paramName);
+
+ sub.AddParam (decl);
+
+ UInt16 value;
+ sub.GetParamVal (paramName, value);
+
+ ByteList::size_type oldSize = stackData.size ();
+ stackData.insert (stackData.end (), sizeof (int), 0); // Make space for an "int"
+
+ *(int*) &stackData[oldSize] = value;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushLong
+// ---------------------------------------------------------------------------
+
+void PrvPushLong (EmSubroutine& sub, ByteList& stackData)
+{
+ // Read a 4-byte long int from the caller's stack, and push it
+ // onto our stack as a 4-byte long int.
+
+ char paramName[20];
+ sprintf (paramName, "param%d", (int) stackData.size ());
+
+ char decl[20];
+ sprintf (decl, "UInt32 %s", paramName);
+
+ sub.AddParam (decl);
+
+ UInt32 value;
+ sub.GetParamVal (paramName, value);
+
+ ByteList::size_type oldSize = stackData.size ();
+ stackData.insert (stackData.end (), sizeof (long), 0); // Make space for a "long int"
+
+ *(long*) &stackData[oldSize] = value;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushDouble
+// ---------------------------------------------------------------------------
+
+void PrvPushDouble (EmSubroutine& sub, ByteList& stackData)
+{
+ UNUSED_PARAM(sub)
+ UNUSED_PARAM(stackData)
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushLongDouble
+// ---------------------------------------------------------------------------
+
+void PrvPushLongDouble (EmSubroutine& sub, ByteList& stackData)
+{
+ UNUSED_PARAM(sub)
+ UNUSED_PARAM(stackData)
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushString
+// ---------------------------------------------------------------------------
+
+void PrvPushString (EmSubroutine& sub, ByteList& stackData, StringList& stringData)
+{
+ // Get the string pointer and clone the string into a new string object.
+
+ char paramName[20];
+ sprintf (paramName, "param%d", (int) stackData.size ());
+
+ char decl[20];
+ sprintf (decl, "char* %s", paramName);
+
+ sub.AddParam (decl);
+
+ emuptr stringPtr;
+ sub.GetParamVal (paramName, stringPtr);
+
+ string strCopy;
+ size_t strLen = EmMem_strlen (stringPtr);
+
+ if (strLen > 0)
+ {
+ strCopy.resize (strLen);
+ EmMem_strcpy (&strCopy[0], stringPtr);
+ }
+
+ // Add this string to the string array.
+
+ stringData.push_back (strCopy);
+
+ // In the stack data byte array, add a pointer to the string.
+
+ ByteList::size_type oldSize = stackData.size ();
+ stackData.insert (stackData.end (), sizeof (char*), 0); // Make space for a "char*"
+ *(const char**) &stackData[oldSize] = (*(stringData.end () - 1)).c_str ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvToFILE
+// ---------------------------------------------------------------------------
+
+FILE* PrvToFILE (emuptr f)
+{
+ if ((HostFILEType*) f == hostLogFile)
+ {
+ return hostLogFILE;
+ }
+
+ return (FILE*) f;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvTmFromHostTm
+// ---------------------------------------------------------------------------
+
+void PrvTmFromHostTm (struct tm& dest, const HostTmType& src)
+{
+ dest.tm_sec = src.tm_sec_;
+ dest.tm_min = src.tm_min_;
+ dest.tm_hour = src.tm_hour_;
+ dest.tm_mday = src.tm_mday_;
+ dest.tm_mon = src.tm_mon_;
+ dest.tm_year = src.tm_year_;
+ dest.tm_wday = src.tm_wday_;
+ dest.tm_yday = src.tm_yday_;
+ dest.tm_isdst = src.tm_isdst_;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvHostTmFromTm
+// ---------------------------------------------------------------------------
+
+void PrvHostTmFromTm (EmProxyHostTmType& dest, const struct tm& src)
+{
+ dest.tm_sec_ = src.tm_sec;
+ dest.tm_min_ = src.tm_min;
+ dest.tm_hour_ = src.tm_hour;
+ dest.tm_mday_ = src.tm_mday;
+ dest.tm_mon_ = src.tm_mon;
+ dest.tm_year_ = src.tm_year;
+ dest.tm_wday_ = src.tm_wday;
+ dest.tm_yday_ = src.tm_yday;
+ dest.tm_isdst_ = src.tm_isdst;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMapAndReturn
+// ---------------------------------------------------------------------------
+
+void PrvMapAndReturn (const void* p, long size, EmSubroutine& sub)
+{
+ emuptr result = EmBankMapped::GetEmulatedAddress (p);
+
+ if (result == EmMemNULL)
+ {
+ EmBankMapped::MapPhysicalMemory (p, size);
+ result = EmBankMapped::GetEmulatedAddress (p);
+ }
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMapAndReturn
+// ---------------------------------------------------------------------------
+
+void PrvMapAndReturn (const string& s, EmSubroutine& sub)
+{
+ ::PrvMapAndReturn (s.c_str (), s.size () + 1, sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReturnString
+// ---------------------------------------------------------------------------
+
+void PrvReturnString (const char* p, EmSubroutine& sub)
+{
+ EmBankMapped::UnmapPhysicalMemory (gResultString.c_str ());
+
+ if (p)
+ {
+ gResultString = p;
+ ::PrvMapAndReturn (gResultString, sub);
+ }
+ else
+ {
+ gResultString.erase ();
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReturnString
+// ---------------------------------------------------------------------------
+
+void PrvReturnString (const string& s, EmSubroutine& sub)
+{
+ EmBankMapped::UnmapPhysicalMemory (gResultString.c_str ());
+
+ gResultString = s;
+
+ ::PrvMapAndReturn (gResultString, sub);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Initialize
+// ---------------------------------------------------------------------------
+
+void Host::Initialize (void)
+{
+ memset (gHandlerTable, 0, sizeof (gHandlerTable));
+
+ gHandlerTable [hostSelectorGetHostVersion] = _HostGetHostVersion;
+ gHandlerTable [hostSelectorGetHostID] = _HostGetHostID;
+ gHandlerTable [hostSelectorGetHostPlatform] = _HostGetHostPlatform;
+ gHandlerTable [hostSelectorIsSelectorImplemented] = _HostIsSelectorImplemented;
+ gHandlerTable [hostSelectorGestalt] = _HostGestalt;
+ gHandlerTable [hostSelectorIsCallingTrap] = _HostIsCallingTrap;
+
+#if HAS_PROFILING
+ gHandlerTable [hostSelectorProfileInit] = _HostProfileInit;
+ gHandlerTable [hostSelectorProfileStart] = _HostProfileStart;
+ gHandlerTable [hostSelectorProfileStop] = _HostProfileStop;
+ gHandlerTable [hostSelectorProfileDump] = _HostProfileDump;
+ gHandlerTable [hostSelectorProfileCleanup] = _HostProfileCleanup;
+ gHandlerTable [hostSelectorProfileDetailFn] = _HostProfileDetailFn;
+ gHandlerTable [hostSelectorProfileGetCycles] = _HostProfileGetCycles;
+#endif
+
+ gHandlerTable [hostSelectorErrNo] = _HostErrNo;
+
+ gHandlerTable [hostSelectorFClose] = _HostFClose;
+ gHandlerTable [hostSelectorFEOF] = _HostFEOF;
+ gHandlerTable [hostSelectorFError] = _HostFError;
+ gHandlerTable [hostSelectorFFlush] = _HostFFlush;
+ gHandlerTable [hostSelectorFGetC] = _HostFGetC;
+ gHandlerTable [hostSelectorFGetPos] = _HostFGetPos;
+ gHandlerTable [hostSelectorFGetS] = _HostFGetS;
+ gHandlerTable [hostSelectorFOpen] = _HostFOpen;
+ gHandlerTable [hostSelectorFPrintF] = _HostFPrintF;
+ gHandlerTable [hostSelectorFPutC] = _HostFPutC;
+ gHandlerTable [hostSelectorFPutS] = _HostFPutS;
+ gHandlerTable [hostSelectorFRead] = _HostFRead;
+ gHandlerTable [hostSelectorRemove] = _HostRemove;
+ gHandlerTable [hostSelectorRename] = _HostRename;
+// gHandlerTable [hostSelectorFReopen] = _HostFReopen;
+// gHandlerTable [hostSelectorFScanF] = _HostFScanF;
+ gHandlerTable [hostSelectorFSeek] = _HostFSeek;
+ gHandlerTable [hostSelectorFSetPos] = _HostFSetPos;
+ gHandlerTable [hostSelectorFTell] = _HostFTell;
+ gHandlerTable [hostSelectorFWrite] = _HostFWrite;
+ gHandlerTable [hostSelectorTmpFile] = _HostTmpFile;
+ gHandlerTable [hostSelectorTmpNam] = _HostTmpNam;
+ gHandlerTable [hostSelectorGetEnv] = _HostGetEnv;
+
+ gHandlerTable [hostSelectorMalloc] = _HostMalloc;
+ gHandlerTable [hostSelectorRealloc] = _HostRealloc;
+ gHandlerTable [hostSelectorFree] = _HostFree;
+
+ gHandlerTable [hostSelectorAscTime] = _HostAscTime;
+ gHandlerTable [hostSelectorClock] = _HostClock;
+ gHandlerTable [hostSelectorCTime] = _HostCTime;
+// gHandlerTable [hostSelectorDiffTime] = _HostDiffTime;
+ gHandlerTable [hostSelectorGMTime] = _HostGMTime;
+ gHandlerTable [hostSelectorLocalTime] = _HostLocalTime;
+ gHandlerTable [hostSelectorMkTime] = _HostMkTime;
+ gHandlerTable [hostSelectorStrFTime] = _HostStrFTime;
+ gHandlerTable [hostSelectorTime] = _HostTime;
+
+ gHandlerTable [hostSelectorMkDir] = _HostMkDir;
+ gHandlerTable [hostSelectorRmDir] = _HostRmDir;
+ gHandlerTable [hostSelectorOpenDir] = _HostOpenDir;
+ gHandlerTable [hostSelectorReadDir] = _HostReadDir;
+ gHandlerTable [hostSelectorCloseDir] = _HostCloseDir;
+
+// gHandlerTable [hostSelectorFStat] = _HostFStat;
+ gHandlerTable [hostSelectorStat] = _HostStat;
+
+ gHandlerTable [hostSelectorGetFileAttr] = _HostGetFileAttr;
+ gHandlerTable [hostSelectorSetFileAttr] = _HostSetFileAttr;
+
+// gHandlerTable [hostSelectorFTruncate] = _HostFTruncate;
+ gHandlerTable [hostSelectorTruncate] = _HostTruncate;
+
+ gHandlerTable [hostSelectorUTime] = _HostUTime;
+
+ gHandlerTable [hostSelectorGremlinIsRunning] = _HostGremlinIsRunning;
+ gHandlerTable [hostSelectorGremlinNumber] = _HostGremlinNumber;
+ gHandlerTable [hostSelectorGremlinCounter] = _HostGremlinCounter;
+ gHandlerTable [hostSelectorGremlinLimit] = _HostGremlinLimit;
+ gHandlerTable [hostSelectorGremlinNew] = _HostGremlinNew;
+
+ gHandlerTable [hostSelectorImportFile] = _HostImportFile;
+ gHandlerTable [hostSelectorExportFile] = _HostExportFile;
+ gHandlerTable [hostSelectorSaveScreen] = _HostSaveScreen;
+ gHandlerTable [hostSelectorImportFileWithID] = _HostImportFileWithID;
+
+ gHandlerTable [hostSelectorExgLibOpen] = _HostExgLibOpen;
+ gHandlerTable [hostSelectorExgLibClose] = _HostExgLibClose;
+ gHandlerTable [hostSelectorExgLibSleep] = _HostExgLibSleep;
+ gHandlerTable [hostSelectorExgLibWake] = _HostExgLibWake;
+ gHandlerTable [hostSelectorExgLibHandleEvent] = _HostExgLibHandleEvent;
+ gHandlerTable [hostSelectorExgLibConnect] = _HostExgLibConnect;
+ gHandlerTable [hostSelectorExgLibAccept] = _HostExgLibAccept;
+ gHandlerTable [hostSelectorExgLibDisconnect] = _HostExgLibDisconnect;
+ gHandlerTable [hostSelectorExgLibPut] = _HostExgLibPut;
+ gHandlerTable [hostSelectorExgLibGet] = _HostExgLibGet;
+ gHandlerTable [hostSelectorExgLibSend] = _HostExgLibSend;
+ gHandlerTable [hostSelectorExgLibReceive] = _HostExgLibReceive;
+ gHandlerTable [hostSelectorExgLibControl] = _HostExgLibControl;
+ gHandlerTable [hostSelectorExgLibRequest] = _HostExgLibRequest;
+
+ gHandlerTable [hostSelectorGetPreference] = _HostGetPreference;
+ gHandlerTable [hostSelectorSetPreference] = _HostSetPreference;
+
+ gHandlerTable [hostSelectorLogFile] = _HostLogFile;
+ gHandlerTable [hostSelectorSetLogFileSize] = _HostSetLogFileSize;
+
+// gHandlerTable [hostSelectorSessionCreate] = _HostSessionCreate;
+// gHandlerTable [hostSelectorSessionOpen] = _HostSessionOpen;
+ gHandlerTable [hostSelectorSessionSave] = _HostSessionSave;
+ gHandlerTable [hostSelectorSessionClose] = _HostSessionClose;
+ gHandlerTable [hostSelectorSessionQuit] = _HostSessionQuit;
+ gHandlerTable [hostSelectorSignalSend] = _HostSignalSend;
+ gHandlerTable [hostSelectorSignalWait] = _HostSignalWait;
+ gHandlerTable [hostSelectorSignalResume] = _HostSignalResume;
+
+#if HAS_TRACER
+ gHandlerTable [hostSelectorTraceInit] = _HostTraceInit;
+ gHandlerTable [hostSelectorTraceClose] = _HostTraceClose;
+ gHandlerTable [hostSelectorTraceOutputT] = _HostTraceOutputT;
+ gHandlerTable [hostSelectorTraceOutputTL] = _HostTraceOutputTL;
+ gHandlerTable [hostSelectorTraceOutputVT] = _HostTraceOutputVT;
+ gHandlerTable [hostSelectorTraceOutputVTL] = _HostTraceOutputVTL;
+ gHandlerTable [hostSelectorTraceOutputB] = _HostTraceOutputB;
+#endif
+
+ gHandlerTable [hostSelectorDbgSetDataBreak] = _HostDbgSetDataBreak;
+ gHandlerTable [hostSelectorDbgClearDataBreak] = _HostDbgClearDataBreak;
+
+ gHandlerTable [hostSelectorSlotMax] = _HostSlotMax;
+ gHandlerTable [hostSelectorSlotRoot] = _HostSlotRoot;
+ gHandlerTable [hostSelectorSlotHasCard] = _HostSlotHasCard;
+
+ gHandlerTable [hostSelectorGetFile] = _HostGetFile;
+ gHandlerTable [hostSelectorPutFile] = _HostPutFile;
+ gHandlerTable [hostSelectorGetDirectory] = _HostGetDirectory;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Reset
+// ---------------------------------------------------------------------------
+
+void Host::Reset (void)
+{
+ ::PrvReleaseAllResources ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Save
+// ---------------------------------------------------------------------------
+
+void Host::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Load
+// ---------------------------------------------------------------------------
+
+void Host::Load (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Dispose
+// ---------------------------------------------------------------------------
+
+void Host::Dispose (void)
+{
+ ::PrvReleaseAllResources ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReleaseAllResources
+// ---------------------------------------------------------------------------
+
+void PrvReleaseAllResources (void)
+{
+ // Close all open files.
+
+ {
+ vector<FILE*>::iterator iter = gOpenFiles.begin ();
+ while (iter != gOpenFiles.end ())
+ {
+ fclose (*iter);
+ ++iter;
+ }
+
+ gOpenFiles.clear ();
+ }
+
+ // Close all open directories.
+
+ {
+ vector<MyDIR*>::iterator iter = gOpenDirs.begin ();
+ while (iter != gOpenDirs.end ())
+ {
+ delete *iter;
+ ++iter;
+ }
+
+ gOpenDirs.clear ();
+
+ // Unmap any mapped gHostDirEnt.
+
+ EmBankMapped::UnmapPhysicalMemory (&gHostDirEnt);
+ }
+
+ // Release all allocated memory.
+
+ {
+ vector<void*>::iterator iter = gAllocatedBlocks.begin ();
+ while (iter != gAllocatedBlocks.end ())
+ {
+ EmBankMapped::UnmapPhysicalMemory (*iter);
+ Platform::DisposeMemory (*iter);
+ ++iter;
+ }
+
+ gAllocatedBlocks.clear ();
+ }
+
+ // Unmap misc memory.
+
+ EmBankMapped::UnmapPhysicalMemory (gResultString.c_str ());
+ EmBankMapped::UnmapPhysicalMemory (&gGMTime);
+ EmBankMapped::UnmapPhysicalMemory (&gLocalTime);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMalloc
+// ---------------------------------------------------------------------------
+
+emuptr PrvMalloc (long size)
+{
+ // Prepare the return value.
+
+ emuptr result = EmMemNULL;
+
+ // Call the function.
+
+ void* newPtr = NULL;
+
+ try
+ {
+ newPtr = Platform::AllocateMemory (size);
+ }
+ catch (...)
+ {
+ }
+
+ // If the call worked, remember the pointer, map
+ // it into emulated space, and return the mapped
+ // pointer to the caller.
+
+ if (newPtr)
+ {
+ gAllocatedBlocks.push_back (newPtr);
+ EmBankMapped::MapPhysicalMemory (newPtr, size);
+
+ result = EmBankMapped::GetEmulatedAddress (newPtr);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvRealloc
+// ---------------------------------------------------------------------------
+
+emuptr PrvRealloc (emuptr p, long size)
+{
+ // Prepare the return value.
+
+ emuptr result = EmMemNULL;
+
+ // Recover the real pointer
+
+ void* oldPtr = EmBankMapped::GetRealAddress (p);
+ if (oldPtr)
+ {
+ // Find the saved pointer in our list so that we can
+ // remove it.
+
+ vector<void*>::iterator iter = gAllocatedBlocks.begin ();
+ while (iter != gAllocatedBlocks.end ())
+ {
+ if (*iter == oldPtr)
+ {
+ // Found the saved pointer. Now try the realloc.
+
+ void* newPtr = NULL;
+
+ try
+ {
+ newPtr = Platform::ReallocMemory (oldPtr, size);
+ }
+ catch (...)
+ {
+ }
+
+ // If that worked, then do the bookkeeping.
+
+ if (newPtr)
+ {
+ gAllocatedBlocks.erase (iter);
+ gAllocatedBlocks.push_back (newPtr);
+
+ EmBankMapped::UnmapPhysicalMemory (oldPtr);
+ EmBankMapped::MapPhysicalMemory (newPtr, size);
+
+ result = EmBankMapped::GetEmulatedAddress (newPtr);
+ }
+ else
+ {
+ // Could not realloc! Just return NULL
+ // (already stored in "result").
+ }
+
+ return result;
+ }
+
+ ++iter;
+ }
+
+ EmAssert (false);
+ // !!! Handle not finding saved pointer
+ }
+ else
+ {
+ EmAssert (false);
+ // !!! Handle not finding real address.
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvFree
+// ---------------------------------------------------------------------------
+
+void PrvFree (emuptr p)
+{
+ // Check the parameters.
+
+ if (p)
+ {
+ // Recover the real pointer
+
+ void* oldPtr = EmBankMapped::GetRealAddress (p);
+ if (oldPtr)
+ {
+ // Find the saved pointer in our list so that we can
+ // remove it.
+
+ vector<void*>::iterator iter = gAllocatedBlocks.begin ();
+ while (iter != gAllocatedBlocks.end ())
+ {
+ if (*iter == oldPtr)
+ {
+ Platform::DisposeMemory (oldPtr);
+
+ EmBankMapped::UnmapPhysicalMemory (*iter);
+ gAllocatedBlocks.erase (iter);
+
+ return;
+ }
+
+ ++iter;
+ }
+
+ EmAssert (false);
+ // !!! Handle not finding saved pointer
+ }
+ else
+ {
+ EmAssert (false);
+ // !!! Handle not finding real address.
+ }
+ }
+}