executor/src/osutil.c

1040 lines
28 KiB
C

/* Copyright 1986, 1989, 1990 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_osutil[] =
"$Id: osutil.c 97 2005-06-22 20:08:38Z ctm $";
#endif
/* Forward declarations in OSUtil.h (DO NOT DELETE THIS LINE) */
#include "rsys/common.h"
#include "QuickDraw.h"
#include "FileMgr.h"
#include "EventMgr.h"
#include "OSUtil.h"
#include "MemoryMgr.h"
#include "Serial.h"
#include "FontMgr.h"
#include "TimeMgr.h"
#include "MenuMgr.h"
#include "ToolboxEvent.h"
#include "rsys/glue.h"
#include "rsys/notmac.h"
#include "rsys/mman.h"
#include "rsys/blockinterrupts.h"
#include "rsys/trapglue.h"
#include "rsys/pstuff.h"
#include "rsys/osutil.h"
#include "rsys/host.h"
#include "rsys/time.h"
#include "rsys/toolevent.h"
#if defined(NEXT) && !defined (OPENSTEP)
#include <appkit/publicWraps.h>
#endif
#if defined(MSDOS)
#include <pc.h>
#endif
/*
* NOTE: HandToHand is not directly called by the outside world.
* Hence, the handle that hp points to is not swapped.
*/
A1(PUBLIC trap, OSErrRET, HandToHand, HIDDEN_Handle *, hp)
{
Handle nh;
Size s;
OSErr err;
if (!hp->p)
{
warning_unexpected ("hp = %p", hp);
/*-->*/ return nilHandleErr;
}
s = GetHandleSize((*hp).p);
if ((err = MemError()))
/*-->*/ return(err);
nh = NewHandle(s);
if ((err = MemError()))
/*-->*/ return(err);
BlockMove(STARH((*hp).p), STARH(nh), s);
(*hp).p = nh;
return noErr;
}
/*
* NOTE: PtrToHand is not directly callable, hence the handle that
* h points to isn't swapped.
*/
A3(PUBLIC trap, OSErrRET, PtrToHand, Ptr, p, HIDDEN_Handle *, h, LONGINT, s)
{
Handle nh;
OSErr err;
nh = NewHandle(s);
if ((err = MemError()))
return(err);
BlockMove(p, STARH(nh), s);
if ((err = MemError()))
return(err);
(*h).p = nh;
return(noErr);
}
A3(PUBLIC trap, OSErrRET, PtrToXHand, Ptr, p, Handle, h, LONGINT, s)
{
OSErr err;
/*
* DO *NOT* use ReallocHandle here. It will fail if the handle is locked.
*/
SetHandleSize(h, s);
if ((err = MemError()))
return(err);
BlockMove(p, STARH(h), s);
if ((err = MemError()))
return(err);
return(noErr);
}
A2(PUBLIC trap, OSErrRET, HandAndHand, Handle, h1, Handle, h2)
{
Size s1 = GetHandleSize(h1), s2 = GetHandleSize(h2);
OSErr err;
SetHandleSize(h2, s1+s2);
if ((err = MemError()))
return(err);
BlockMove(STARH(h1), STARH(h2)+s2, s1);
if ((err = MemError()))
return(err);
return(noErr);
}
A3(PUBLIC trap, OSErrRET, PtrAndHand, Ptr, p, Handle, h, LONGINT, s1)
{
Size s2 = GetHandleSize(h);
OSErr err;
SetHandleSize(h, s1+s2);
if ((err = MemError()))
return(err);
BlockMove(p, STARH(h)+s2, s1);
if ((err = MemError()))
return(err);
return(noErr);
}
/* NOTE: This set of tables was created by running a test program on
the Mac. It replaces the tables that were hand created from
(incomplete) information in Inside Macintosh */
PRIVATE unsigned char casefold[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20, '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[','\\', ']', '^', '_',
'a', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~',0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0xCB,0x89,0x80,0xCC,0x81,0x82,0x83,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x84,0x97,0x98,0x99,0x85,0xCD,0x9C,0x9D,0x9E,0x86,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xAE,0xAF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCE,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
PRIVATE unsigned char diacfold[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20, '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[','\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',0x7F,
'A', 'A', 'C', 'E', 'N', 'O', 'U', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e',
'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u',
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE, 'O',
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA, 'a', 'o',0xBD,0xBE, 'o',
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0x20, 'A', 'A', 'O',0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7, 'y',0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
PRIVATE unsigned char bothfold[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20, '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[','\\', ']', '^', '_',
'a', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~',0x7F,
'A', 'A', 'C', 'E', 'N', 'O', 'U', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E',
'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U',
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE, 'O',
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA, 'A', 'O',0xBD,0xAE, 'O',
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA, 'A', 'A', 'O',0xCE,0xCE,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7, 'Y',0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
PRIVATE unsigned char order[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x21,0x22,0x23,0x28,0x29,0x2A,0x2B,0x2C,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,
0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
0x47,0x48,0x57,0x59,0x5D,0x5F,0x66,0x68,0x6A,0x6C,0x72,0x74,0x76,0x78,0x7A,0x7E,
0x8C,0x8E,0x90,0x92,0x95,0x97,0x9E,0xA0,0xA2,0xA4,0xA7,0xA9,0xAA,0xAB,0xAC,0xAD,
0xAE,0x4E,0x58,0x5B,0x5E,0x61,0x67,0x69,0x6B,0x6D,0x73,0x75,0x77,0x79,0x7C,0x83,
0x8D,0x8F,0x91,0x93,0x96,0x99,0x9F,0xA1,0xA3,0xA5,0xA8,0xAF,0xB0,0xB1,0xB2,0xB3,
0x4A,0x4C,0x5A,0x60,0x7B,0x7F,0x98,0x4F,0x50,0x51,0x52,0x53,0x54,0x5C,0x62,0x63,
0x64,0x65,0x6E,0x6F,0x70,0x71,0x7D,0x84,0x85,0x86,0x87,0x88,0x9A,0x9B,0x9C,0x9D,
0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0x94,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0x4D,0x81,
0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0x55,0x8A,0xCC,0x56,0x89,
0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0x26,0x27,0xD4,0x20,0x49,0x4B,0x80,0x82,0x8B,
0xD5,0xD6,0x24,0x25,0x2D,0x2E,0xD7,0xD8,0xA6,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
A5(PUBLIC, LONGINT, ROMlib_RelString, unsigned char *, s1, unsigned char *, s2,
BOOLEAN, casesig, BOOLEAN, diacsig, LONGINT, d0)
{
register INTEGER n1, n2;
register unsigned char *s, *t;
unsigned char c1, c2;
s = s1;
t = s2;
n1 = d0 >> 16;
n2 = d0 & 0xFFFF;
if (n1 > n2)
n1 = n2;
if (casesig && diacsig) {
while (n1--) {
c1 = *s++;
c2 = *t++;
if ((c1 == 0x20 && c2 == 0xCA) ||
(c2 == 0x20 && c1 == 0xCA))
/*-->*/ continue;
if (c1 != c2)
/*-->*/ return order[c1] < order[c2] ? -1 : 1;
}
} else if ( casesig && !diacsig) {
while (n1--) {
c1 = *s++;
c2 = *t++;
if ((c1 == 0x20 && c2 == 0xCA) ||
(c2 == 0x20 && c1 == 0xCA))
/*-->*/ continue;
if (diacfold[c1] != diacfold[c2])
/*-->*/ return order[diacfold[c1]] < order[diacfold[c2]] ? -1 : 1;
}
} else if (!casesig && diacsig) {
while (n1--) {
c1 = *s++;
c2 = *t++;
if ((c1 == 0x20 && c2 == 0xCA) ||
(c2 == 0x20 && c1 == 0xCA))
/*-->*/ continue;
if (casefold[c1] != casefold[c2])
/*-->*/ return order[casefold[c1]] < order[casefold[c2]] ? -1 : 1;
}
} else { /*!casesig && !diacsig*/
while (n1--) {
c1 = *s++;
c2 = *t++;
if ((c1 == 0x20 && c2 == 0xCA) ||
(c2 == 0x20 && c1 == 0xCA))
/*-->*/ continue;
if (bothfold[c1] != bothfold[c2])
/*-->*/ return order[bothfold[c1]] < order[bothfold[c2]] ? -1 : 1;
}
}
n1 = d0 >> 16;
if (n1 != n2)
/*-->*/ return n1 < n2 ? -1 : 1;
return 0;
}
A4(PUBLIC trap, INTEGERRET, RelString, StringPtr, s1, StringPtr, s2,
BOOLEAN, casesig, BOOLEAN, diacsig)
{
return ROMlib_RelString((unsigned char *) s1 + 1, (unsigned char *) s2 + 1,
casesig, diacsig,
(LONGINT) (unsigned char) s1[0] << 16 | (unsigned char) s2[0]);
}
A4(PUBLIC trap, BOOLEANRET, EqualString, StringPtr, s1, StringPtr, s2,
BOOLEAN, casesig, BOOLEAN, diacsig)
{
return RelString(s1, s2, casesig, diacsig) ? FALSE : TRUE;
}
A2(PUBLIC, int, ROMlib_strcmp, const Byte *, s1, const Byte *, s2) /* INTERNAL */
{
register int n1 = U(s1[0]), n2 = U(s2[0]);
register unsigned char *p1 = (unsigned char *) s1+1,
*p2 = (unsigned char *) s2+1, c1, c2;
#if !defined (LETGCCWAIL)
c1 = 0;
c2 = 0;
#endif /* LETGCCWAIL */
while (n1 && n2 && ((c1 = bothfold[U(*p1)]) == (c2 = bothfold[U(*p2)]))) {
n1--;
n2--;
p1++;
p2++;
}
if (!n1)
return n2 ? -1 : 0;
if (!n2)
return 1;
else
return c1 < c2 ? -1 : 1;
}
A3(PUBLIC, void, ROMlib_UprString, StringPtr, s, BOOLEAN, diac, INTEGER, len)
{
unsigned char *p, *ep, *base;
if (diac)
base = casefold;
else
base = bothfold;
for (p = s, ep = p + len; p != ep; p++)
*p = base[U(*p)];
}
A2(PUBLIC trap, void, UprString, StringPtr, s, BOOLEAN, diac)
{
ROMlib_UprString(s+1, diac, (INTEGER) (unsigned char) s[0]);
}
A1(PUBLIC, void, GetDateTime, LONGINT *, mactimepointer)
{
#undef Time /* Why is this here? */
if (mactimepointer) {
unsigned long msecs;
msecs = msecs_elapsed ();
*mactimepointer = CL (UNIXTIMETOMACTIME (ROMlib_start_time.tv_sec)
+ (((ROMlib_start_time.tv_usec / 1000) + msecs)
/ 1000));
}
}
A1(PUBLIC trap, OSErrRET, ReadDateTime, LONGINT *, secs)
{
GetDateTime(secs);
return(noErr);
}
A1(PUBLIC trap, OSErrRET, SetDateTime, LONGINT, mactime)
{
#if !defined(SYSV) && !defined (CYGWIN32)
struct timeval thetime;
thetime.tv_sec = MACTIMETOGUNIXTIME(mactime);
thetime.tv_usec = 0;
if (settimeofday(&thetime, 0) < 0)
return(clkWrErr);
else
return(noErr);
#else /* defined(SYSV) */
#warning "SetDateTime not implemented"
return clkWrErr;
#endif /* defined(SYSV) */
}
/* beginning of code to test */
PRIVATE unsigned long long
secsinminutes (ULONGINT nminutes)
{
return nminutes * 60;
}
PRIVATE unsigned long long
secsinhours (ULONGINT nhours)
{
return nhours * secsinminutes((LONGINT) 60);
}
PRIVATE unsigned long long
secsindays (ULONGINT ndays)
{
return ndays * secsinhours((LONGINT) 24);
}
PRIVATE INTEGER daysinmonths[13] = {
0,
31,
31 + 28,
31 + 28 + 31,
31 + 28 + 31 + 30,
31 + 28 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
};
PRIVATE INTEGER daysinleapmonths[13] = {
0,
31,
31 + 29,
31 + 29 + 31,
31 + 29 + 31 + 30,
31 + 29 + 31 + 30 + 31,
31 + 29 + 31 + 30 + 31 + 30,
31 + 29 + 31 + 30 + 31 + 30 + 31,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
};
PRIVATE unsigned long long
secsinmonths (ULONGINT nmonths)
{
return secsindays((ULONGINT) daysinmonths[nmonths]);
}
PRIVATE unsigned long long
secsinleapmonths (ULONGINT nmonths)
{
return secsindays((ULONGINT) daysinleapmonths[nmonths]);
}
PRIVATE unsigned long long
daysinyears (ULONGINT year)
{
return (ULONGINT) 365 * year + year / 4 - year / 100 + year / 400;
}
A1(PRIVATE, BOOLEAN, isleap, ULONGINT, year)
{
return !(year % 4) && (year % 100 || !(year % 400));
}
/* month January = 1, hour Midnight = 0 */
PUBLIC long long
ROMlib_long_long_secs (INTEGER year, INTEGER month, INTEGER day, INTEGER hour,
INTEGER minute, INTEGER second)
{
/* #warning Make this work for years < 1904 ... it's probably wrong */
long long retval;
if (year < 1904)
warning_unexpected ("year = %d", year);
retval = secsindays(daysinyears(year-1) - daysinyears(1903));
retval += secsinmonths(month-1);
retval += secsindays(day-1);
retval += secsinhours(hour);
retval += secsinminutes(minute);
retval += second;
if (isleap(year) && month > 2)
retval += secsindays((ULONGINT) 1);
return retval;
}
#define N_SECS_IN_MINUTE (60L)
#define N_SECS_IN_HOUR (60L * N_SECS_IN_MINUTE)
#define N_SECS_IN_DAY (24L * N_SECS_IN_HOUR)
#define N_SECS_IN_YEAR (365L * N_SECS_IN_DAY)
#define N_SECS_IN_LEAP_YEAR (366L * N_SECS_IN_DAY)
PRIVATE long long cutoffs[(1LL << 32) / N_SECS_IN_YEAR + 1];
PRIVATE void
init_cutoffs (void)
{
int i;
long long cutoff;
i = 0;
cutoff = N_SECS_IN_LEAP_YEAR;
while (cutoff < (1LL << 32))
{
cutoffs[i] = cutoff;
if (i % 4)
cutoff += N_SECS_IN_YEAR;
else
cutoff += N_SECS_IN_LEAP_YEAR;
++i;
}
cutoffs[i] = cutoff;
}
PUBLIC void
date_to_swapped_fields (long long mactime, INTEGER *yearp, INTEGER *monthp,
INTEGER *dayp, INTEGER *hourp, INTEGER *minutep,
INTEGER *secondp, INTEGER *dayofweekp,
INTEGER *dayofyearp, INTEGER *weekofyearp)
{
/*
* NOTE: the function below relies on the start date being 1/1/1904. It is
* clear that Apple picked that date so there would be no funky non-
* leap years (1900 was one).
*/
long long secs_left;
ULONGINT approx_year, days, secs_approx_year;
INTEGER month, day, hour, minute;
static BOOLEAN cutoffs_inited_p = FALSE;
if (!cutoffs_inited_p)
{
init_cutoffs ();
cutoffs_inited_p = TRUE;
}
if (mactime < 0)
warning_unexpected (NULL_STRING);
if (dayofweekp)
*dayofweekp = CW((mactime / N_SECS_IN_DAY + 5) % 7 + 1);
if (mactime >= (1LL << 32))
{
warning_unexpected ("impossible mactime = %lld", mactime);
approx_year = 0;
}
else
{
for (approx_year = 0; mactime >= cutoffs[approx_year]; ++approx_year)
;
}
days = 365 * approx_year + (approx_year+3)/4;
secs_left = mactime - (days * N_SECS_IN_DAY);
secs_approx_year = isleap(approx_year+1904) ?
N_SECS_IN_LEAP_YEAR : N_SECS_IN_YEAR;
if (secs_left >= secs_approx_year) {
approx_year++;
secs_left -= secs_approx_year;
}
*yearp = CW(approx_year + 1904);
if (secs_left < 0)
{
warning_unimplemented ("This code is flat out wrong");
secs_left %= N_SECS_IN_LEAP_YEAR;
if (secs_left < 0)
secs_left += N_SECS_IN_LEAP_YEAR;
warning_unexpected ("bad date");
}
if (dayofyearp)
*dayofyearp = CW (secs_left / N_SECS_IN_DAY + 1);
if (weekofyearp)
*weekofyearp = CW (secs_left / N_SECS_IN_DAY / 7 + 1);
if (isleap(approx_year+1904)) {
for (month = 0;
secsinleapmonths(month+1) <= (unsigned long long) secs_left;
month++)
;
secs_left -= secsinleapmonths(month);
} else {
for (month = 0;
secsinmonths(month+1) <= (unsigned long long) secs_left;
month++)
;
secs_left -= secsinmonths(month);
}
*monthp = CW(month+1);
day = secs_left / N_SECS_IN_DAY;
*dayp = CW(day + 1);
secs_left -= day * N_SECS_IN_DAY;
hour = secs_left / N_SECS_IN_HOUR;
*hourp = CW(hour);
secs_left -= hour * N_SECS_IN_HOUR;
minute = secs_left / N_SECS_IN_MINUTE;
*minutep = CW(minute);
secs_left -= minute * N_SECS_IN_MINUTE;
*secondp = CW(secs_left);
}
/* end of code to test */
/*
* NOTE: not callable from the outside world directly
*/
A2(PUBLIC trap, void, Date2Secs, DateTimeRec *, d, LONGINT *, s)
{
LONGINT l;
l = ROMlib_long_long_secs (CW (d->year), CW (d->month), CW (d->day),
CW (d->hour), CW (d->minute), CW (d->second));
*s = l;
}
A2(PUBLIC trap, void, Secs2Date, LONGINT, mactime, DateTimeRec *, d)
{
date_to_swapped_fields ((unsigned long) mactime, &d->year, &d->month,
&d->day, &d->hour, &d->minute, &d->second,
&d->dayOfWeek, 0, 0);
}
A1(PUBLIC, void, GetTime, DateTimeRec *, d)
{
LONGINT secs;
GetDateTime(&secs);
Secs2Date(CL(secs), d);
}
A1(PUBLIC, void, SetTime, DateTimeRec *, d)
{
LONGINT secs;
Date2Secs(d, &secs);
SetDateTime(secs);
}
typedef enum {Read, Write} ReadWriteType;
#define VALID 0xA8
A0(PRIVATE, void, setdefaults)
{
SPValid = VALID;
SPAlarm = SPATalkB = SPATalkA = SPConfig = 0;
SPPrint = SPPortB = SPPortA = CW(baud9600 | stop10 | data8 | noParity);
SPFont = CW(geneva - 1);
SPKbd = 0x63;
SPVolCtl = 3;
SPClikCaret = 0x88;
SPMisc2 = 0x4C;
}
A1(PRIVATE, OSErr, openparam, INTEGER *, rnp)
{
static char paramname[] = PARAMRAMMACNAME;
OSErr err;
err = FSOpen((StringPtr) paramname, Cx(BootDrive), rnp);
if (err == fnfErr) {
if ((err = Create((StringPtr) paramname, Cx(BootDrive), TICK("unix"),
TICK("pram"))) == noErr)
err = FSOpen((StringPtr) paramname, Cx(BootDrive), rnp);
}
return err;
}
PUBLIC LONGINT ROMlib_GMTcorrect;
A0(PRIVATE, void, deriveglobals)
{
struct tm *tm, tml, tmg, *tmlater, *tmearlier;
time_t unixtimenow, gmtimenow, ltimenow;
unixtimenow = (ROMlib_start_time.tv_sec
+ ((ROMlib_start_time.tv_usec / 1000 + msecs_elapsed ())
/ 1000));
tm = localtime(&unixtimenow);
BlockMove((Ptr) tm, (Ptr) &tml, (Size) sizeof(tml));
tm = gmtime(&unixtimenow);
BlockMove((Ptr) tm, (Ptr) &tmg, (Size) sizeof(tmg));
if (tml.tm_year != tmg.tm_year) {
tmlater = tml.tm_year > tmg.tm_year ? &tml : &tmg;
tmearlier = tml.tm_year > tmg.tm_year ? &tmg : &tml;
/* Adjust the day of year */
tmlater->tm_yday = tmearlier->tm_yday + 1;
}
ltimenow = (tml.tm_yday * 24 * 60 * 60) + /* seconds per day */
(tml.tm_hour * 60 * 60) + /* seconds per hour */
(tml.tm_min * 60) + tml.tm_sec;
gmtimenow = (tmg.tm_yday * 24 * 60 * 60) +
(tmg.tm_hour * 60 * 60) +
(tmg.tm_min * 60) + tmg.tm_sec;
ROMlib_GMTcorrect = gmtimenow - ltimenow;
KeyThresh = CW((short) ((SPKbd >> 4) & 0xF) * 4);
KeyRepThresh = CW((short) (SPKbd & 0xF) * 4);
MenuFlash = CW((short) (SPMisc2 >> 2) & 3);
CaretTime = CL((short) (SPClikCaret & 0xF) * 4);
DoubleTime = CL((short) (SPClikCaret & 0xF0) / 4);
}
A0(PUBLIC trap, OSErrRET, InitUtil) /* IMII-380 */
{
INTEGER rn;
SysParmType sp;
LONGINT count;
OSErr err;
BOOLEAN badread;
#if !defined(LETGCCWAIL)
badread = FALSE;
#endif
if ((err = openparam(&rn)) == noErr) {
count = sizeof(sp);
if (FSRead(rn, &count, (Ptr) &sp) == noErr && sp.valid == VALID &&
count == sizeof(sp)) {
SPValid = sp.valid;
SPATalkA = sp.aTalkA;
SPATalkB = sp.aTalkB;
SPConfig = sp.config;
SPPortA = sp.portA;
SPPortB = sp.portB;
SPAlarm = sp.alarm;
SPFont = sp.font;
SPKbd = CW(sp.kbdPrint) >> 8;
SPPrint = CW(sp.kbdPrint);
SPVolCtl = CW(sp.volClik) >> 8;
SPClikCaret = CW(sp.volClik);
#if !defined (BIGENDIAN)
SPMisc2 = sp.misc;
#else
SPMisc2 = sp.misc >> 8;
#warning this is broken
#endif
badread = FALSE;
} else
badread = TRUE;
}
if (err != noErr || badread)
setdefaults();
deriveglobals();
if (err)
err = prInitErr;
else
err = FSClose(rn);
return err;
}
A0(PUBLIC, SysPPtr, GetSysPPtr) /* IMII-381 */
{
return (SysPPtr) &SPValid;
}
A0(PUBLIC trap, OSErrRET, WriteParam) /* IMII-382 */
{
INTEGER rn;
SysParmType sp;
LONGINT count;
OSErr err, err2;
err = prWrErr;
if (openparam(&rn) == noErr) {
sp.valid = SPValid;
sp.aTalkA = SPATalkA;
sp.aTalkB = SPATalkB;
sp.config = SPConfig;
sp.portA = SPPortA;
sp.portB = SPPortB;
sp.alarm = SPAlarm;
sp.font = SPFont;
sp.kbdPrint = CW((short) (SPKbd << 8) | (SPPrint & 0xff));
sp.volClik = CW((short) (SPVolCtl << 8) | (SPClikCaret & 0xff));
#if !defined (BIGENDIAN)
sp.misc = SPMisc2;
#else
sp.misc = SPMisc2 << 8;
#endif
count = sizeof(sp);
if (FSWrite(rn, &count, (Ptr) &sp) == noErr && count == sizeof(sp))
err = noErr;
deriveglobals();
ROMlib_beepedonce = FALSE;
err2 = FSClose(rn);
if (err == noErr)
err = err2;
}
return err;
}
A2(PUBLIC trap, void, Enqueue, QElemPtr, e, QHdrPtr, h)
{
HIDDEN_QElemPtr *qpp;
virtual_int_state_t block;
block = block_virtual_ints ();
for (qpp = (HIDDEN_QElemPtr *) &h->qHead; (*qpp).p && MR((*qpp).p) != e;
qpp = (HIDDEN_QElemPtr *) MR((*qpp).p))
;
if (!(*qpp).p) {
e->evQElem.qLink = 0;
if (h->qTail)
MR(h->qTail)->evQElem.qLink = RM(e);
else
h->qHead = RM(e);
h->qTail = RM(e);
}
restore_virtual_ints (block);
}
A2(PUBLIC trap, OSErrRET, Dequeue, QElemPtr, e, QHdrPtr, h)
{
HIDDEN_QElemPtr *qpp;
OSErr retval;
virtual_int_state_t block;
retval = qErr;
block = block_virtual_ints ();
for (qpp = (HIDDEN_QElemPtr *) &h->qHead; (*qpp).p && MR((*qpp).p) != e;
qpp = (HIDDEN_QElemPtr *) MR((*qpp).p))
;
if ((*qpp).p) {
(*qpp).p = e->evQElem.qLink;
if (MR(h->qTail) == e)
h->qTail = qpp == (HIDDEN_QElemPtr *) &h->qHead ? (QElemPtr) 0 : RM((QElemPtr) qpp);
retval = noErr;
}
restore_virtual_ints (block);
return retval;
}
A2(PUBLIC, LONGINT, NGetTrapAddress, INTEGER, n, INTEGER, ttype) /* IMII-384 */
{
LONGINT retval;
retval = (LONGINT) ((ttype == OSTrap) ?
(LONGINT) CL((long) ostraptable[n&(NOSENTRIES-1)])
:
(LONGINT) CL((long) tooltraptable[n&(NTOOLENTRIES-1)]));
warning_trace_info ("n = 0x%x, ttype = %d, retval = %p", (uint16) n, ttype,
(void *) retval);
return retval;
}
#if !defined(BINCOMPAT)
A2(PUBLIC, void, SetTrapAddress, LONGINT, addr, /* IMII-384 NOT SUPPORTED */
INTEGER, n)
{
}
#endif
PRIVATE BOOLEAN shouldbeawake;
A0(PUBLIC, void, C_ROMlib_wakeup)
{
// fprintf (stderr, "W");
// fflush (stderr);
#if defined (SDL)
SDL_mutexP (ROMlib_shouldbeawake_mutex);
#endif
shouldbeawake = TRUE;
#if defined (SDL)
SDL_mutexV (ROMlib_shouldbeawake_mutex);
#endif
};
/* argument n is in 1/60ths of a second */
A2 (PUBLIC trap, void, Delay, LONGINT, n, LONGINT *, ftp) /* IMII-384 */
{
if (n > 0)
{
#if defined (CYGWIN32)
clock_t finish_clocks;
void __attribute__ ((stdcall)) Sleep(int32 dwMilliseconds);
finish_clocks = clock() + n * CLOCKS_PER_SEC / 60;
while (clock () < finish_clocks)
{
Sleep(0); /* Give up current CPU timeslice */
check_virtual_interrupt ();
}
#elif defined (MSDOS)
unsigned long finish_msecs;
/* Busy looping is fine here. */
finish_msecs = msecs_elapsed () + n * 1000 / 60;
while (msecs_elapsed () < finish_msecs)
{
check_virtual_interrupt ();
}
#else /* !MSDOS */
TMTask tm;
#if defined (USE_BSD_SIGNALS)
int old_mask;
old_mask = sigblock (sigmask (SIGALRM));
#else
sigset_t to_block;
sigset_t old_mask;
sigemptyset (&to_block);
sigaddset (&to_block, SIGALRM);
sigprocmask (SIG_BLOCK, &to_block, &old_mask);
#endif
#if defined (SDL)
SDL_mutexP (ROMlib_shouldbeawake_mutex);
#endif
shouldbeawake = FALSE;
tm.tmAddr = RM ((ProcPtr) P_ROMlib_wakeup);
InsTime ((QElemPtr) &tm);
// fprintf (stderr, "p");
// fflush (stderr);
PrimeTime ((QElemPtr) &tm, n * 1000 / 60);
while (!shouldbeawake)
{
#if defined (SDL)
// fprintf (stderr, "C");
// fflush (stderr);
SDL_CondWait (ROMlib_shouldbeawake_cond, ROMlib_shouldbeawake_mutex);
// fprintf (stderr, "c");
// fflush (stderr);
#elif !defined(USE_BSD_SIGNALS)
sigset_t zero_mask;
sigemptyset(&zero_mask);
sigsuspend (&zero_mask); /* NOTE: this will allow both UNIX signals
and our thread_set_state kludges */
#else
sigsetmask (0);
#endif
check_virtual_interrupt ();
}
RmvTime ((QElemPtr) &tm);
#if defined (SDL)
SDL_mutexV (ROMlib_shouldbeawake_mutex);
#endif
#if defined (USE_BSD_SIGNALS)
sigsetmask (old_mask);
#else
sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif
#endif /* !MSDOS */
}
/* Note: we're really called from a stub, so no CL() is needed here. */
if (ftp)
*ftp = TickCount ();
}
P1(PUBLIC pascal trap, void, SysBeep, INTEGER, i) /* SYSTEM DEPENDENT */
{
#if defined(MAC)
DebugStr("\004Beep");
#elif defined(X) || defined(NEXTSTEP) || defined (CYGWIN32)
host_beep_at_user ();
#elif defined(MSDOS)
sound(440);
Delay(i, (LONGINT *) 0);
sound(0);
#else
write(1, "\7", 1);
#endif
}
PUBLIC char ROMlib_phoneyrom[10] = {
0, 0, 0, 0, 0, 0, 0, 0, 0x06, 0x7C,
};
A2(PUBLIC trap, void, Environs, INTEGER *, rom, INTEGER *, machine)
{
unsigned char rom8, rom9;
rom8 = ((unsigned char *)ROMlib_phoneyrom)[8];
rom9 = ((unsigned char *)ROMlib_phoneyrom)[9];
*rom = CW (rom9);
*machine = CW (rom8 + 1);
}
#if !defined(NEXT) && !defined(SYN68K)
INTEGER ROMlib_processor = env68020;
#else
INTEGER ROMlib_processor = env68040;
#endif
#if !defined(SYN68K)
INTEGER ROMlib_hasFPU = TRUE;
#endif
A2(PUBLIC trap, OSErrRET, SysEnvirons, INTEGER, vers, SysEnvRecPtr, p)
{
#if defined(NEXT)
ROMlib_processor = ROMlib_040 ? env68040 : env68030;
#endif
if (vers <= 0)
/*-->*/ return envBadVers;
p->environsVersion = CW (vers);
p->machineType = CWC (53);
p->systemVersion = SysVersion;
#if !defined (SYN68K)
p->processor = CW(ROMlib_processor);
p->hasFPU = ROMlib_hasFPU;
#else /* SYN68K */
p->processor = CWC(env68040);
p->hasFPU = FALSE;
#endif /* SYN68K */
p->hasColorQD = TRUE;
p->keyBoardType = CWC(envAExtendKbd);
p->atDrvrVersNum = 0;
p->sysVRefNum = BootDrive;
return vers <= SYSRECVNUM ? noErr : envVersTooBig;
}
A0(PUBLIC, void, SetUpA5)
{
}
A0(PUBLIC, void, RestoreA5)
{
}
#define TRUE32b 1
A1(PUBLIC, void, GetMMUMode, INTEGER *, ip) /* IMV-592 */
{
*ip = CWC(TRUE32b);
}
A1(PUBLIC, void, SwapMMUMode, Byte *, bp) /* IMV-593 */
{
*bp = CB(TRUE32b);
}
A1(PUBLIC, LONGINT, StripAddress, LONGINT, l) /* IMV-593 */
{
return l;
}