executor/src/toolutil.c

733 lines
16 KiB
C

/* Copyright 1986, 1989, 1990, 1995 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_toolutil[] =
"$Id: toolutil.c 63 2004-12-24 18:19:43Z ctm $";
#endif
/* Forward declarations in ToolboxUtil.h (DO NOT DELETE THIS LINE) */
#include "rsys/common.h"
#include "ResourceMgr.h"
#include "QuickDraw.h"
#include "CQuickDraw.h"
#include "ToolboxUtil.h"
#include "OSUtil.h"
#include "MemoryMgr.h"
#include "rsys/cquick.h"
#include "rsys/mman.h"
#include "rsys/glue.h"
#include "SANE.h"
#include "rsys/float.h"
#include "rsys/floatconv.h"
#include "rsys/next.h" /* for ROMlib_info */
#include "rsys/string.h"
#include "rsys/mman_private.h"
P2(PUBLIC pascal trap, Fixed, FixRatio, INTEGER, n, INTEGER, d)
{
if (!d)
return(n < 0 ? 0x80000001 : 0x7fffffff);
return(((LONGINT) n << 16) / d);
}
P2(PUBLIC pascal trap, Fixed, FixMul, Fixed, a, Fixed, b)
{
int sign = 1;
ULONGINT ms1, ms2, ls1, ls2, mm, ml, lm, ll;
if (a < 0) {
a = -a;
sign = -sign;
}
if (b < 0) {
b = -b;
sign = -sign;
}
ms1 = (ULONGINT) a >> 16;
ms2 = (ULONGINT) b >> 16;
ls1 = (ULONGINT) a & 0xffff;
ls2 = (ULONGINT) b & 0xffff;
mm = ms1 * ms2;
if (mm >= (1L << 15))
return sign == 1 ? 0x7FFFFFFF : 0x80000000;
ml = ms1 * ls2;
lm = ls1 * ms2;
ll = ls1 * ls2;
mm <<= 16;
mm += ml + lm + (ll >> 16);
if (mm & 0x80000000)
return sign == 1 ? 0x7FFFFFFF : 0x80000000;
return(sign*mm);
}
P1(PUBLIC pascal trap, INTEGER, FixRound, Fixed, x)
{
return((x>>16) + ((x & 0x8000L) != 0));
}
P1(PUBLIC pascal trap, StringHandle, NewString, StringPtr, s)
{
HIDDEN_Handle retval;
PtrToHand((Ptr) s, &retval, (LONGINT)U(s[0]) + 1);
return((StringHandle) retval.p);
}
P2(PUBLIC pascal trap, void, SetString, StringHandle, h, StringPtr, s)
{
PtrToXHand((Ptr) s, (Handle) h, (LONGINT)U(s[0]) + 1);
}
A2(PUBLIC, Handle, ROMlib_getrestid, ResType, rest, /* INTERNAL */
INTEGER, id)
{
Handle retval;
retval = GetResource(rest, id);
if (retval)
LoadResource(retval);
return retval;
}
PUBLIC StringHandle ROMlib_phoney_name_string;
PRIVATE StringHandle
get_phoney_name_resource (void)
{
if (!ROMlib_phoney_name_string)
{
char *name = "";
#if defined (linux) || defined (MACOSX)
name = getlogin ();
if (!name)
name = getenv ("LOGNAME");
if (!name)
name = "";
#endif
int len;
len = strlen (name);
ROMlib_phoney_name_string = (StringHandle) NewHandleSys (len+1);
if (ROMlib_phoney_name_string)
{
HSetRBit ((Handle) ROMlib_phoney_name_string);
str255_from_c_string (STARH (ROMlib_phoney_name_string), name);
}
}
return ROMlib_phoney_name_string;
}
P1(PUBLIC pascal trap, StringHandle, GetString, INTEGER, i)
{
StringHandle retval;
retval = (StringHandle) ROMlib_getrestid(TICK("STR "), i);
if (i == -16096 && !retval)
retval = get_phoney_name_resource ();
return retval;
}
A3(PUBLIC, void, GetIndString, StringPtr, s, INTEGER, sid, INTEGER, index)
{
Handle retval;
char *p, *ep, *op;
retval = GetResource(TICK("STR#"), sid);
LoadResource(retval);
if (ResError() != noErr || *(INTEGER *) STARH(retval) < index) {
s[0] = 0;
/*-->*/ return;
}
p = (char *) STARH(retval) + 2;
while (--index)
p += 1 + U(*p);
for (ep = p + 1 + U(*p), op = (char *)s; p != ep; *op++ = *p++)
;
}
A4(PRIVATE, int, cmpstrings, char *, p, char *, ep, char *, p1, LONGINT, len)
{
int retval = TRUE;
while (retval && p != ep && len--)
if (*p++ != *p1++)
retval = FALSE;
return(retval);
}
/*
* TODO: find out mroe about what Munger does. If it's returning an
* undocumented error return in D0, does that mean that the global memory
* error location isn't changed?
*/
#warning Munger returns undocumented error return in D0
#define RETURN(x) do { retval = (x); goto DONE; } while (FALSE)
#warning We never check for offset greater than HandleSize -- check and fix
#warning We also return -1 even though the Mac may return something different
P6(PUBLIC pascal trap, LONGINT, Munger, Handle, h, LONGINT, off, Ptr, p1,
LONGINT, len1, Ptr, p2, LONGINT, len2)
{
char *p, *ep;
LONGINT hs, tomove;
LONGINT retval;
MM_SLAM ("entry");
p = (char *) STARH(h) + off;
ep = (char *) STARH(h) + (hs = GetHandleSize(h));
if (p1 && len1) {
while (!cmpstrings(p, ep, (char *) p1, len1))
p++;
if (p == ep)
RETURN (-1);
if (ep - p < len1)
{
if (p != (char *) STARH(h) + off)
RETURN (-1);
else
len1 = ep - p;
}
off = p - (char *) STARH(h);
} else if (len1 < 0)
len1 = hs - off;
if (!p2 && p1)
RETURN (off);
tomove = ep - p - len1;
if (len1 > len2) {
BlockMove((Ptr) p+len1, (Ptr) p+len2, tomove);
SetHandleSize(h, hs + len2 - len1);
p = (char *) STARH(h) + off;
} else if (len1 < len2) {
SetHandleSize(h, hs + len2 - len1);
p = (char *) STARH(h) + off;
BlockMove((Ptr) p+len1, (Ptr) p+len2, tomove);
}
while (len2--)
*p++ = *p2++;
RETURN (p - (char *) STARH(h));
DONE:
MM_SLAM ("exit");
EM_D0 &= 0xFFFF0000; /* for now ... we never have an error */
return retval;
}
#undef RETURN
P3(PUBLIC pascal trap, void, PackBits, HIDDEN_Ptr *, sp, HIDDEN_Ptr *, dp, INTEGER, len)
{
char *ip, *op, *ep, *erp, *markp, c;
ip = (char *) MR((*sp).p);
op = (char *) MR((*dp).p);
ep = ip + len;
erp = ip + len - 2;
markp = op++;
while (ip != ep)
{
while (ip != ep
&& (ip >= erp || *ip != *(ip+1) || *ip != *(ip+2))
&& op - markp - 2 < 127)
*op++ = *ip++;
if (op != markp+1)
{
*markp = op - markp - 2;
}
else
op--;
if (ip != ep)
{
markp = ip;
c = *ip++;
while (ip != ep && c == *ip && ip - markp - 1 < 127)
ip++;
*op++ = -(ip - markp - 1);
*op++ = c;
}
markp = op++;
}
(*sp).p = (Ptr) RM (ip);
(*dp).p = (Ptr) RM (op-1);
}
#define UNPACK_BITS_BODY(out_type) \
do { \
const int8 *ip; \
out_type *op, *ep; \
\
ip = (const int8 *) MR (sp->p); \
op = (out_type *) MR (dp->p); \
ep = (out_type *) ((int8 *) op + len); \
\
while (op < ep) \
{ \
int count = *ip++; \
if (count < 0) \
{ \
out_type v = *(out_type *)ip; \
ip += sizeof (out_type); \
for (count = MIN (1 - count, ep - op); count > 0; count--) \
*op++ = v; \
} \
else \
{ \
unsigned bytes = MIN (count + 1, ep - op) * sizeof (out_type); \
memmove (op, ip, bytes); \
op += bytes / sizeof *op; \
ip += bytes; \
} \
} \
\
sp->p = (Ptr) RM (ip); \
dp->p = (Ptr) RM (op); \
} while (FALSE)
void
unpack_int16_bits (HIDDEN_Ptr *sp, HIDDEN_Ptr *dp, INTEGER len)
{
/* This is used when unpacking 16 bpp PICT bitmaps. */
UNPACK_BITS_BODY (int16);
}
P3(PUBLIC pascal trap, void, UnpackBits, HIDDEN_Ptr *, sp, HIDDEN_Ptr *, dp, INTEGER, len)
{
UNPACK_BITS_BODY (int8);
}
P2(PUBLIC pascal trap, BOOLEAN, BitTst, Ptr, bp, LONGINT, bn)
{
bp += bn / 8;
return((*bp&(1<<((7-bn)&7)))!=0);
}
P2(PUBLIC pascal trap, void, BitSet, Ptr, bp, LONGINT, bn)
{
bp += bn / 8;
*bp |= 1<<((7-bn)&7);
}
P2(PUBLIC pascal trap, void, BitClr, Ptr, bp, LONGINT, bn)
{
bp += bn / 8;
*bp &= ~(1<<((7-bn)&7));
}
P2(PUBLIC pascal trap, LONGINT, BitAnd, LONGINT, a, LONGINT, b)
{
return(a&b);
}
P2(PUBLIC pascal trap, LONGINT, BitOr, LONGINT, a, LONGINT, b)
{
return(a|b);
}
P2(PUBLIC pascal trap, LONGINT, BitXor, LONGINT, a, LONGINT, b)
{
return(a^b);
}
P1(PUBLIC pascal trap, LONGINT, BitNot, LONGINT, a)
{
return(~a);
}
P2(PUBLIC pascal trap, LONGINT, BitShift, LONGINT, a, INTEGER, n)
{
if (n < 0) {
n = -n;
return ((n %= 64) & 32) ? 0 : (ULONGINT) a >> n;
} else
return ((n %= 64) & 32) ? 0 : (ULONGINT) a << n;
}
P1(PUBLIC pascal trap, INTEGER, HiWord, LONGINT, a)
{
return(a>>16);
}
P1(PUBLIC pascal trap, INTEGER, LoWord, LONGINT, a)
{
return(a&0xFFFF);
}
P3(PUBLIC pascal trap, void, LongMul, LONGINT, a, LONGINT, b, Int64Bit *, c)
{
int sign;
ULONGINT ha, hb, la, lb, halb, lahb;
int carry;
if ((a > 0 && b < 0) || (a < 0 && b > 0))
sign = -1;
else
sign = 1;
if (a < 0)
a = -a;
if (b < 0)
b = -b;
ha = a >> 16;
hb = b >> 16;
la = a & 0xFFFF;
lb = b & 0xFFFF;
halb = ha * lb;
lahb = la * hb;
c->hiLong = CL(ha * hb);
c->loLong = CL(la * lb);
c->hiLong = CL(CL(c->hiLong) + (halb >> 16));
c->hiLong = CL(CL(c->hiLong) + (lahb >> 16));
carry = CL(c->loLong) >> 31;
c->loLong = CL(CL(c->loLong) + (halb << 16));
carry += (halb >> 15) & 1;
c->loLong = CL(CL(c->loLong) + (lahb << 16));
carry += (lahb >> 15) & 1;
carry >>= 1;
c->hiLong = CL(CL(c->hiLong) + (carry));
if (sign == -1) {
c->hiLong = ~c->hiLong;
if (c->loLong)
c->loLong = CL(~CL(c->loLong) + 1);
else
c->hiLong = CL(CL(c->hiLong) + 1);
}
}
A2(PUBLIC, void, ScreenRes, INTEGER *, hp, INTEGER *, vp)
{
*hp = ScrHRes;
*vp = ScrVRes;
}
P1(PUBLIC pascal trap, PatHandle, GetPattern, INTEGER, id)
{
return((PatHandle) ROMlib_getrestid(TICK("PAT "), id));
}
A3(PUBLIC, void, GetIndPattern, Byte *, op, INTEGER, plistid, INTEGER, index)
{
Handle retval;
char *p, *ep;
retval = GetResource(TICK("PAT#"), plistid);
LoadResource(retval);
if (ResError() != noErr || *(INTEGER *) STARH(retval) < index) {
return;
}
p = (char *) STARH(retval) + 2 + 8 * (index - 1);
for (ep = p + 8; p != ep; *op++ = *p++)
;
}
P1(PUBLIC pascal trap, CursHandle, GetCursor, INTEGER, id)
{
return((CursHandle) ROMlib_getrestid(TICK("CURS"), id));
}
/*
* Note: ShieldCursor is found in qd/qCursor.c
*/
P1(PUBLIC pascal trap, PicHandle, GetPicture, INTEGER, id)
{
PicHandle retval;
retval = (PicHandle) ROMlib_getrestid(TICK("PICT"), id);
return retval;
}
P2(PUBLIC pascal trap, LONGINT, DeltaPoint, Point, a, Point, b)
{
return (((LONGINT)a.v - b.v) << 16) | (unsigned short)(a.h - b.h);
}
A1(PRIVATE, Fixed, minvert, Fixed, f) /* wants postive number */
{
return(((0x80000000 / (ULONGINT)f) << 1) & 0x7FFFFFFF);
}
PRIVATE Fixed sloptab[46] = {
0x80000001, 0x00394a30, 0x001ca2d7, 0x001314bd, 0x000e4cf5,
0x000b6e17, 0x000983ad, 0x000824f3, 0x00071d88, 0x00065051,
0x0005abd9, 0x00052501, 0x00046462, 0x000454db, 0x000402c2,
0x0003bb68, 0x00037cc7, 0x00034556, 0x000313e3, 0x0002e77a,
0x0002bf5b, 0x00029ae7, 0x000279af, 0x00025b19, 0x00023efc,
0x000224fe, 0x00020ce1, 0x0001f66e, 0x0001e177, 0x0001cdd6,
0x0001bb68, 0x0001aa0e, 0x000199af, 0x00018a35, 0x00017689,
0x00016dab, 0x0001605b, 0x000153b9, 0x000147aa, 0x00013c22,
0x00013117, 0x0001267f, 0x00011c51, 0x00011287, 0x00010919,
0x00010000
};
P1(PUBLIC pascal trap, Fixed, SlopeFromAngle, INTEGER, a)
{
int sign, recip;
auto Fixed retval; /* cc -a problems */
if (a < 0)
a -= 360 * ((a / 360) - 1);
if (a > 360)
a %= 360;
if (a > 180)
a -= 180;
if (a < 90) {
sign = -1;
a = 180 - a;
} else
sign = 1;
if (a > 135) {
recip = TRUE;
a = 270 - a;
} else
recip = FALSE;
retval = sloptab[a - 90];
if (recip)
retval = minvert(retval);
if (sign == -1)
retval = -retval;
return(retval);
}
P1(PUBLIC pascal trap, INTEGER, AngleFromSlope, Fixed, s)
{
int neg, inv, retval;
ULONGINT *ulp;
if (s < 0) {
s = -s;
neg = TRUE;
} else
neg = FALSE;
if (s < 0x10000) {
if (s)
s = minvert(s);
else
s = 0x7fffffff;
inv = TRUE;
} else
inv = FALSE;
for (ulp = (ULONGINT *)sloptab+1; *ulp > (ULONGINT) s ; ulp++)
;
if (*(ulp-1) - s < s - *ulp)
ulp--;
#if !defined(__GNUC__) || defined(FIXEDGCC)
retval = ulp - (ULONGINT *)sloptab + 90;
#else
{
ULONGINT * volatile temp;
temp = (ULONGINT *) sloptab;
retval = ulp - temp + 90;
}
#endif
if (inv)
retval = 270 - retval;
if (neg)
retval = 180 - retval;
return(retval ? retval : 180);
}
P2(PUBLIC pascal trap, Fract, FracMul, Fract, x, Fract, y) /* IMIV-64 */
{
Extended z;
if ((uint32) x == 0x80000000 && (uint32) y == 0x80000000)
/*-->*/ return 0; /* this is a deliberate "bug" according to IMIV-63
but nevertheless the mac+ returns 0 here */
z = Frac2X(x) * Frac2X(y);
return X2Frac(&z);
}
P2(PUBLIC pascal trap, Fixed, FixDiv, Fixed, x, Fixed, y) /* IMIV-64 */
{
Extended z;
z = Fix2X(x) / Fix2X(y);
return X2Fix(&z);
}
P2(PUBLIC pascal trap, Fract, FracDiv, Fract, x, Fract, y) /* IMIV-64 */
{
Extended z;
z = Frac2X(x) / Frac2X(y);
return X2Frac(&z);
}
#define MAXLONG2FIX 0x7FFF
#define MINLONG2FIX - ((LONGINT) MAXLONG2FIX + 1)
#define POSOVERFLOW 0x7FFFFFFF
#define NEGOVERFLOW 0x80000000
P1(PUBLIC pascal trap, Fixed, Long2Fix, LONGINT, x) /* IMIV-65 */
{
if (x > MAXLONG2FIX)
/*-->*/ return POSOVERFLOW;
else if (x < MINLONG2FIX)
/*-->*/ return NEGOVERFLOW;
else
/*-->*/ return x << 16;
}
P1(PUBLIC pascal trap, LONGINT, Fix2Long, Fixed, x) /* IMIV-65 */
{
return x >= 0 ?
(x + (1L << 15)) >> 16
:
0xFFFF0000 | ((x + (1L << 15)) >> 16);
}
#define MAXFIX2FRAC 0x1FFFF
#define MINFIX2FRAC - ((LONGINT) MAXFIX2FRAC + 1)
P1(PUBLIC pascal trap, Fract, Fix2Frac, Fixed, x) /* IMIV-65 */
{
if (x > MAXFIX2FRAC)
/*-->*/ return POSOVERFLOW;
else if (x < MINFIX2FRAC)
/*-->*/ return NEGOVERFLOW;
else
/*-->*/ return x << 14;
}
P1(PUBLIC pascal trap, Fixed, Frac2Fix, Fract, x) /* IMIV-65 */
{
return x >= 0 ?
(x + (1 << 13)) >> 14
:
0xFFFC0000 | ((x + (1 << 13)) >> 14);
}
A1(PUBLIC, Extended, Fix2X, Fixed, x) /* IMIV-65 */
{
return (Extended) x / (1L << 16);
}
#define MAXX2FIX MAXLONG2FIX
#define MINX2FIX MINLONG2FIX
A1(PUBLIC, Fixed, X2Fix, Extended *, xp) /* IMIV-65 */
{
Extended x;
if ((x = *xp) >= 0) {
if (x > MAXX2FIX)
/*-->*/ return POSOVERFLOW;
else
/*-->*/ return (Fixed) (x * (1L << 16) + .5);
} else {
if (x < MINX2FIX)
/*-->*/ return NEGOVERFLOW;
else
/*-->*/ return (Fixed) (x * (1L << 16) - .5);
}
}
A1(PUBLIC, Extended, Frac2X, Fract, x) /* IMIV-65 */
{
return (Extended) x / (1L << 30);
}
#define BEYONDMAXX2FRAC 2
#define MINX2FRAC -2
A1(PUBLIC, Fract, X2Frac, Extended *, xp) /* IMIV-65 */
{
Extended x;
if ((x = *xp) >= 0) {
if (x >= BEYONDMAXX2FRAC)
/*-->*/ return POSOVERFLOW;
else
/*-->*/ return (Fract) (x * (1L << 30) + .5);
} else {
if (x < MINX2FRAC)
/*-->*/ return NEGOVERFLOW;
else
/*-->*/ return (Fract) (x * (1L << 30) - .5);
}
}
#if defined (BINCOMPAT)
A3(PUBLIC trap, void, R_Fix2X, void *, dummyretpc, Fixed, x, /* INTERNAL */
extended80 *, ret)
{
#if 0
extended96 temp;
asm("fmovel %1, fp0\n\t"
"fdivl #0x10000, fp0\n\t"
"fmovex fp0, %0" : "=m" (temp) : "m" (x) : "fp0");
X96TO80(temp, *ret);
#else
register ieee_t n = x;
n /= 0x10000;
ieee_to_x80 (n, ret);
#endif
}
A3(PUBLIC trap, void, R_Frac2X, void *, dummyretpc, Fract, x, /* INTERNAL */
extended80 *, ret)
{
#if 0
extended96 temp;
asm("fmovel %1, fp0\n\t"
"fdivl #0x40000000, fp0\n\t"
"fmovex fp0, %0" : "=m" (temp) : "m" (x) : "fp0");
X96TO80(temp, *ret);
#else
register ieee_t n = x;
n /= 0x40000000;
ieee_to_x80 (n, ret);
#endif
}
P1(PUBLIC pascal trap, Fixed, R_X2Fix, extended80 *, x)
{
#if 0
extended96 temp;
Fixed retval;
X80TO96(*x, temp);
asm("fmovex %1, fp0\n\t"
"fmull #0x10000, fp0\n\t"
"fmovel fp0, %0" : "=g" (retval) : "m" (temp) : "fp0");
return retval;
#else
register ieee_t n = x80_to_ieee (x);
n *= 0x10000;
return (Fixed) n;
#endif
}
P1(PUBLIC pascal trap, Fract, R_X2Frac, extended80 *, x)
{
#if 0
extended96 temp;
Fract retval;
X80TO96(*x, temp);
asm("fmovex %1, fp0\n\t"
"fmull #0x40000000, fp0\n\t"
"fmovel fp0, %0" : "=g" (retval) : "m" (temp) : "fp0");
return retval;
#else
register ieee_t n = x80_to_ieee (x);
n *= 0x40000000;
return (Fract) n;
#endif
}
#endif /* BINCOMPAT */