assert.c
#include <stdio.h>
#include <stdlib.h>

void _assert(char *expr, const char *filename, unsigned int linenumber)
{
	fprintf(stderr, "Assert(%s) failed at line %u in file %s.\n",
		expr, linenumber, filename);
	abort();
}
ctype.c
/* Copyright 1987 Manx Software Systems, Inc */

#define	_U	0x01	/* Upper case */
#define	_L	0x02	/* Lower case */
#define	_D	0x04	/* Decimal digit */
#define	_X	0x08	/* heXadecimal digit */
#define	_S	0x10	/* Spacing character */
#define	_C	0x20	/* Control character */
#define	_P	0x40	/* Punctuation */
#define	_B	0x80	/* Blank */

char _ctype[1+256] = {
	0,								/*	EOF */
	_C,		_C,		_C,		_C,		/*	nul	soh	stx	etx	*/
	_C,		_C,		_C,		_C,		/*	eot	enq	ack	bel	*/
	_C,		_C|_S,	_C|_S,	_C|_S,	/*	bs	ht	nl	vt	*/
	_C|_S,	_C|_S,	_C,		_C,		/*	ff	cr	so	si	*/
	_C,		_C,		_C,		_C,		/*	dle	dc1	dc2	dc3	*/
	_C,		_C,		_C,		_C,		/*	dc4	nak	syn	etb	*/
	_C,		_C,		_C,		_C,		/*	can	em	sub	esc	*/
	_C,		_C,		_C,		_C,		/*	fs	gs	rs	us	*/
	_B|_S,	_P,		_P,		_P,		/*	sp	!	"	#	*/
	_P,		_P,		_P,		_P,		/*	$	%	&	'	*/
	_P,		_P,		_P,		_P,		/*	(	)	*	+	*/
	_P,		_P,		_P,		_P,		/*	,	-	.	/	*/
	_D|_X,	_D|_X,	_D|_X,	_D|_X,	/*	0	1	2	3	*/
	_D|_X,	_D|_X,	_D|_X,	_D|_X,	/*	4	5	6	7	*/
	_D|_X,	_D|_X,	_P,		_P,		/*	8	9	:	;	*/
	_P,		_P,		_P,		_P,		/*	<	=	>	?	*/
	_P,		_U|_X,	_U|_X,	_U|_X,	/*	@	A	B	C	*/
	_U|_X,	_U|_X,	_U|_X,	_U,		/*	D	E	F	G	*/
	_U,		_U,		_U,		_U,		/*	H	I	J	K	*/
	_U,		_U,		_U,		_U,		/*	L	M	N	O	*/
	_U,		_U,		_U,		_U,		/*	P	Q	R	S	*/
	_U,		_U,		_U,		_U,		/*	T	U	V	W	*/
	_U,		_U,		_U,		_P,		/*	X	Y	Z	[	*/
	_P,		_P,		_P,		_P,		/*	\	]	^	_	*/
	_P,		_L|_X,	_L|_X,	_L|_X,	/*	`	a	b	c	*/
	_L|_X,	_L|_X,	_L|_X,	_L,		/*	d	e	f	g	*/
	_L,		_L,		_L,		_L,		/*	h	i	j	k	*/
	_L,		_L,		_L,		_L,		/*	l	m	n	o	*/
	_L,		_L,		_L,		_L,		/*	p	q	r	s	*/
	_L,		_L,		_L,		_L,		/*	t	u	v	w	*/
	_L,		_L,		_L,		_P,		/*	x	y	z	{	*/
	_P,		_P,		_P,		_C,		/*	|	}	~	del	*/
} ;
isalnum.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isalnum(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isalnum

int
isalnum(int c)
{
	return((_ctype+1)[c]&(_L|_U|_D));
}

isalpha.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isalpha(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isalpha

int
isalpha(int c)
{
	return((_ctype+1)[c]&(_L|_U));
}

isascii.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isascii(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isascii

int
isascii(int c)
{
	return(((c)&0x80)==0);
}

iscntrl.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int iscntrl(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef iscntrl

int
iscntrl(int c)
{
	return((_ctype+1)[c]&(_C));
}

isdigit.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isdigit(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isdigit

int
isdigit(int c)
{
	return((_ctype+1)[c]&(_D));
}

isgraph.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isgraph(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isgraph

int
isgraph(int c)
{
	return((_ctype+1)[c]&(_P|_L|_U|_D));
}

islower.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int islower(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef islower

int
islower(int c)
{
	return((_ctype+1)[c]&(_L));
}

isprint.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isprint(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isprint

int
isprint(int c)
{
	return((_ctype+1)[c]&(_P|_L|_U|_D|_B));
}

ispunct.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int ispunct(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef ispunct

int
ispunct(int c)
{
	return((_ctype+1)[c]&(_P));
}

isspace.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isspace(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isspace

int
isspace(int c)
{
	return((_ctype+1)[c]&(_W));
}

isupper.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isupper(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isupper

int
isupper(int c)
{
	return((_ctype+1)[c]&(_U));
}

isxdigit.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int isxdigit(int c);
 *
 *
 *	Description
 *
 *
 *
 *
 *	Returns
 *
 *
 */

#include <ctype.h>
#undef isxdigit

int
isxdigit(int c)
{
	return((_ctype+1)[c]&(_H));
}

ldiv.a68
; Copyright (C) 1984 by Manx Software Systems, Inc.
;:ts=8
;
	public	.divs
.divs:		;long divide	(primary = primary/secondary)
	movem.l	d1/d4,-(sp)
	clr.l	d4			;mark result as positive
	tst.l	d0
	bpl.s	prim_ok
	neg.l	d0
	add.w	#1,d4			;mark as negative
prim_ok:
	tst.l	d1
	bpl.s	sec_ok
	neg.l	d1
	eor.w	#1,d4			;flip sign of result
sec_ok:
	jsr	comdivide
chksign:
	tst.w	d4
	beq.s	posres
	neg.l	d0
posres:
	movem.l	(sp)+,d1/d4
	tst.l	d0
	rts
;
	public	.mods
.mods:		;long remainder	(primary = primary%secondary)
	movem.l	d1/d4,-(sp)
	clr.l	d4			;mark result as positive
	tst.l	d0
	bpl.s	rprim_ok
	neg.l	d0
	add.w	#1,d4			;mark as negative
rprim_ok:
	tst.l	d1
	bpl.s	rsec_ok
	neg.l	d1
rsec_ok:
	jsr	comdivide
	move.l	d1,d0
	jmp	chksign
;
	public	.modu
.modu:		;unsigned long remainder	(primary = primary%secondary)
	move.l	d1,-(sp)
	jsr	comdivide
	move.l	d1,d0
	move.l	(sp)+,d1
	tst.l	d0
	rts
;
	public	.divu
.divu:		;unsigned long divide		(primary = primary/secondary)
	move.l	d1,-(sp)
	jsr	comdivide
	move.l	(sp)+,d1
	tst.l	d0
	rts

; divide (dx,ax) by (bx,cx):
;	quotient in (dx,ax)
;	remainder in (bx,cx)
comdivide:
	movem.l	d2/d3,-(sp)
	swap	d1
	tst.w	d1
	bne	hardldv
	swap	d1
	move.w	d1,d3		;get divisor
	move.w	d0,d2		;save second part of dividend
	clr.w	d0		;get first part of dividend
	swap	d0
	divu	d3,d0		;do first divide
	move.l	d0,d1		;copy first remainder
	swap	d0		;get first quotient
	move.w	d2,d1		;get back second part of dividend
	divu	d3,d1		;do second divide
	move.w	d1,d0		;get second quotient
	clr.w	d1		;remainder is small
	swap	d1		;get it
	movem.l	(sp)+,d2/d3
	rts			;and return

hardldv:
	swap	d1
	move.l	d1,d3		;save divisor
	move.l	d0,d1		;copy dividend
	clr.w	d1		;set up remainder
	swap	d1
	swap	d0		;set up quotient
	clr.w	d0
	move.l	#16-1,d2		;do 16 times
1$
	add.l	d0,d0		;shift the quotient
	addx.l	d1,d1		;shift the remainder
	cmp.l	d1,d3		;check if big enough to subtract
	bhi	2$
	sub.l	d3,d1		;yes, so subtract it
	add.w	#1,d0		;and add one to quotient
2$
	dbf	d2,1$		;and loop till done
	movem.l	(sp)+,d2/d3
	rts

lmul.a68
; Copyright (C) 1984 by Manx Software Systems, Inc.
;:ts=8
;
	public	.mulu
.mulu:		;unsigned long multiply	(primary = primary*secondary)
;
	movem.l	d1/d2/d3,-(sp)
	move.w	d1,d2
	mulu	d0,d2		;d0.l * d1.l
	move.l	d1,d3
	swap	d3
	mulu	d0,d3		;d0.l * d1.h
	swap	d3
	clr.w	d3
	add.l	d3,d2
	swap	d0
	mulu	d1,d0		;d0.h * d1.l
	swap	d0
	clr.w	d0
	add.l	d2,d0
	movem.l	(sp)+,d1/d2/d3
	rts
;
localeco.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	struct lconv *localeconv(void);
 *
 *
 *	Description
 *
 *		The localeconv function sets the components of an object with type
 *	struct lconv with values appropriate for the formatting of numeric
 *	quantities (monetary and otherwise) according to the rules of the current
 *	locale.
 *
 *		The members of the structure with type char * are strings, any of which
 *	(except decimal_point) can point to "", to indicate that the value is not
 *	available in the current locale or is of zero length. The members with type
 *	char are nonnegative numbers, any of which can be CHAR_MAX to indicate that
 *	the value is not available in the current locale. The members include the
 *	following:
 *
 *	char *decimal_point
 *		The decimal-point character is used to format non-monetary quantities.
 *
 *	char *thousands_sep
 *		The character used to separate groups of digits to the left of the
 *		decimal-point character in formatted non-monetary quantities.
 *
 *	char *grouping
 *		A string whose elements indicate the size of each group of digits in
 *		formatted non-monetary quantities.
 *
 *	char *int_curr_symbol
 *		The international currency symbol applicable to the current locale. The
 *		first three characters contain the alphabetic international currency
 *		symbol in accordance with those specified in ISO 4217 Codes for the
 *		Representation of Currency and Funds. The fourth character (immediately
 *		preceding the null character) is the character used to separate the
 *		international currency symbol from the monetary quantity.
 *
 *	char *currency_symbol
 *		The local currency symbol applicable to the current locale.
 *
 *	char *mon_decimal_point
 *		The decimal-point used to format monetary quantities.
 *
 *	char *mon_thousands_sep
 *		The separator for groups of digits to the left of the decimal-point in
 *		formatted monetary quantities.
 *
 *	char *mon_grouping
 *		A string whose elements indicate the size of each group of digits in
 *		formatted monetary quantities.
 *
 *	char *positive_sign
 *		The string used to indicate a nonnegative-valued formatted monetary
 *		quantity.
 *
 *	char *negative_sign
 *		The string used to indicate a negative-valued formatted monetary
 *		quantity.
 *
 *	char int_frac_digits
 *		The number of fractional digits (those to the right of the decimal-
 *		point) to be displayed in a internationally formatted monetary
 *		quantity.
 *
 *	char frac_digits
 *		The number of fractional digits (those to the right of the decimal-
 *		point) to be displayed in a formatted monetary quantity.
 *
 *	char p_cs_precedes
 *		Set to 1 or 0 if the currency_symbol respectively precedes or succeeds
 *
 *	char frac_digits
 *		The number of fractional digits (those to the right of the decimal-
 *		point) to be displayed in a formatted monetary quantity.
 *
 *	char p_cs_precedes
 *		Set to 1 or 0 if the currency_symbol respectively precedes or succeeds
 *		the value for a nonnegative formatted monetary quantity.
 *
 *	char p_sep_by_space
 *		Set to 1 or 0 if the currency_symbol respectively is or is not
 *		separated by a space from the value for a nonnegative formatted
 *		monetary quantity.
 *
 *	char n_cs_precedes
 *		Set to 1 or 0 if the currency_symbol respectively precedes or succeeds
 *		the value for a negative formatted monetary quantity.
 *
 *	char n_sep_by_space
 *		Set to 1 or 0 if the currency_symbol respectively is or is not
 *		separated by a space from the value for a negative formatted monetary
 *		quantity.
 *
 *	char p_sign_posn
 *		Set to a value indicating the positioning of the positive_sign for a
 *		nonnegative formatted monetary quantity.
 *
 *	char n_sign_posn
 *		Set to a value indicating the positioning of the negative_sign for a
 *		negative formatted monetary quantity.
 *
 *		The elements of grouping and mon_grouping are interpreted according to
 *	the following:
 *
 *	CHAR_MAX	No further grouping is to be performed.
 *
 *	0			The previous element is to be repeatedly used for the remainder
 *				of the digits.
 *
 *	other		The value is the number of digits that comprise the current
 *				group. The next element is examined to determine the size of
 *				the next group of digits to the left of the current group.
 *
 *		The value of p_sign_posn and n_sign_posn is interpreted according to
 *	the following:
 *
 *	0	Parentheses surround the quantity and currency_symbol.
 *
 *	1	The sign string precedes the quantity and currency_symbol.
 *
 *	2	The sign string succeeds the quantity and currency_symbol.
 *
 *	3	The sign string immediately precedes the currency_symbol.
 *
 *	4	The sign string immediately succeeds the currency_symbol.
 *
 *		The implementation shall behave as if no library function calls the
 *	localeconv function.
 *
 *
 *	Returns
 *
 *		The localeconv function returns a pointer to the filled-in object. The
 *	structure pointed to by the return value shall not be modified by the
 *	program, but may be overwritten by a subsequent call to the localeconv
 *	function. In addition, calls to the setlocale function with categories
 *	LC_ALL, LC_MONETARY, or LC_NUMERIC may overwrite the contents of the
 *	structure.
 */

#include <locale.h>
#include <limits.h>

struct lconv *
localeconv(void)
{
	static struct lconv l = {
		".",		/* char *decimal_point;		*/
		"",			/* char *thousands_sep;		*/
		"",			/* char *grouping;			*/
		"",			/* char *int_curr_symbol;	*/
		"",			/* char *currency_symbol;	*/
		"",			/* char *mon_decimal_point;	*/
		"",			/* char *mon_thousands_sep;	*/
		"",			/* char *mon_grouping;		*/
		"",			/* char *positive_sign;		*/
		"",			/* char *negative_sign;		*/
		CHAR_MAX,	/* char int_frac_digits;	*/
		CHAR_MAX,	/* char frac_digits;		*/
		CHAR_MAX,	/* char p_cs_precedes;		*/
		CHAR_MAX,	/* char p_sep_by_space;		*/
		CHAR_MAX,	/* char n_cs_precedes;		*/
		CHAR_MAX,	/* char n_sep_by_space;		*/
		CHAR_MAX,	/* char p_sign_posn;		*/
		CHAR_MAX,	/* char n_sign_posn;		*/
	};

	return (&l);
}

makefile
CC=qcc
AS=as
CFLAGS=
AFLAGS=
O=oss

.c.$O:
	$(CC) -o $@ $(CFLAGS) $*.c
.a68.$O:
	$(AS) -o $@ $(AFLAGS) $*.a68

CLIB=\
	assert.$O ctype.$O isalnum.$O isalpha.$O isascii.$O \
	iscntrl.$O isdigit.$O isgraph.$O islower.$O isprint.$O \
	ispunct.$O isspace.$O isupper.$O isxdigit.$O setlocal.$O \
	localeco.$O signal.$O \
	ldiv.$O lmul.$O peek.$O setjmp.$O toupper.$O tolower.$O

clib:	$(CLIB)

peek.a68
; Copyright (C) 1984 by Manx Software Systems, Inc.
; :ts=8
;
	public _peekl
_peekl
	move.l	4(sp),a0
	btst.b	#0,7(sp)
	bne	1$
	move.l	(a0),d0
	rts
1$
	move.l	#0,d0
	move.w	#3,d1
2$
	lsl.l	#8,d0
	move.b	(a0)+,d0
	dbra	d1,2$
	rts
;
	public _peekw
_peekw
	move.l	#0,d0
	move.l	4(sp),a0
	btst.b	#0,7(sp)
	bne	1$
	move.w	(a0),d0
	rts
1$
	move.b	(a0)+,d0
	lsl.w	#8,d0
	move.b	(a0),d0
	rts
;
	public _peek
	public _peekb
_peekb
_peek
	move.l	4(sp),a0
	move.l	#0,d0
	move.b	(a0),d0
	rts
;
	public _pokel
_pokel
	move.l	4(sp),a0
	lea	8(sp),a1
	move.w	#3,d1
.2
	move.b	(a1)+,(a0)+
	dbra	d1,.2
	rts
;
	public _pokew
_pokew
	move.l	4(sp),a0
	IF INT32
	move.b	10(sp),(a0)+
	move.b	11(sp),(a0)+
	ELSE
	move.b	8(sp),(a0)+
	move.b	9(sp),(a0)+
	ENDC
	rts
;
	public _pokeb
	public _poke
_pokeb
_poke
	move.l	4(sp),a0
	IF INT32
	move.b	11(sp),(a0)
	ELSE
	move.b	9(sp),(a0)
	ENDC
	rts
;
raise.c

raise()
{
}

setjmp.a68
; Copyright Manx Software Systems, Inc. 1988.  All rights reserved.
; :ts=8

;	This routine saves the return PC and registers d1-d7 and a1-a7 in
;	the buffer passed into the routine. Zero is returned.

	public _setjmp
_setjmp
	move.l	(sp)+,d0
	move.l	(sp),a0
	movem.l	d0-d7/a1-a7,(a0)
	move.l	d0,a0
	move.l	#0,d0
	jmp	(a0)

;	This routine restores the registers found in the buffer and
;	returns the value passed in as a second argument.

	public	_longjmp
_longjmp
	move.l	4(sp),a0
	IF INT32
	move.l	8(sp),d0
	ELSE
	move.w	8(sp),d0
	ENDC
	bne	.1
	move.l	#1,d0
.1
	movem.l	4(a0),d1-d7/a1-a7
	move.l	(a0),a0
	jmp	(a0)
;
setlocal.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	char *setlocale(int category, const char *locale);
 *
 *
 *	Description
 *
 *		The setlocale function selects the appropriate portion of the program's
 *	locale as specified by the category and locale arguments. The setlocale
 *	function may be used to change or query the program's entire current locale
 *	or portions thereof. The value LC_ALL for category names the program's
 *	entire locale; the other values for category name only a portion of the
 *	program's locale. LC_COLLATE affects the behavior of the strcoll and
 *	strxfrm functions. LC_CTYPE affects the behavior of the character handling
 *	functions and the multibyte functions. LC_MONETARY affects the monetary
 *	formatting information returned by the localeconv function. LC_NUMERIC
 *	affects the decimal-point character for the formatted input/output
 *	functions and the string conversion functions, as well as the non-monetary
 *	formatting information returned by the localeconv function. LC_TIME affects
 *	the behavior of the strftime function.
 *
 *		A value of "C" for locale specifies the minimal environment for C
 *	translation; a value of "" for locale specifies the implementation-defined
 *	native environment. Other implementation-defined strings may be passed as
 *	the second argument to setlocale.
 *
 *		At program startup, the equivalent of 
 *
 *			setlocale(LC_ALL, "C");
 *
 *	is executed.
 *
 *		The implementation shall behave as if no library function calls the
 *	setlocale function.
 *
 *
 *	Returns
 *
 *		If a pointer to a string is given for locale and the selection can be
 *	honored, the setlocale function returns the string associated with the
 *	specified category for the new locale. If the selection cannot be honored,
 *	the setlocale function returns a null pointer and the program's locale is
 *	not changed.
 *
 *		A null pointer for locale causes the setlocale function to return the
 *	string associated with the category for the program's current locale; the
 *	program's locale is not changed.
 *
 *		The string returned by the setlocale functions is such that a
 *	subsequent call with that string and its associated category will restore
 *	that part of the program's locale. The string returned shall not be
 *	modified by the program, but may be overwritten by a subsequent call to the
 *	setlocale function.
 */

#include <locale.h>
#include <string.h>

char *
setlocale(int category, const char *loc)
{
	if ((strcmp(loc,"C") == 0) || (strcmp(loc,"") == 0))
		return("C");  /* only 'C' supported */
	return(0);
}

signal.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	void (*signal(int sig, void (*func)(int)))(int);
 *
 *
 *	Description
 *
 *		The signal function chooses one of three ways in which receipt of the
 *	signal number sig is to be subsequently handled. If the value of func is
 *	SIG_DFL, default handling for that signal will occur. If the value of func
 *	is SIG_IGN, the signal will be ignored. Otherwise, func shall point to a
 *	function to be called when that signal occurs. Such a function is called a
 *	signal handler.
 *
 *		When a signal occurs, if func points to a function, first the
 *	equivalent of signal(sig, SIG_DFL); is executed or an implementation-
 *	defined blocking of the signal is performed. (If the value of sig is
 *	SIGILL, whether the reset to SIG_DFL occurs is implementation-defined.)
 *	Next, the equivalent of (*func)(sig); is executed. The function func may
 *	terminate by executing a return statement or by calling the abort, exit, or
 *	longjump function. If func executes a return statement and the value of sig
 *	was SIGFPE or any other implementation-defined value corresponding to a
 *	computational exception, the behavior is undefined. Otherwise, the program
 *	will resume execution at the point it was interrupted.
 *
 *		If the signal occurs other than as the result of calling the abort or
 *	raise function, the behavior is undefined if the signal handler calls any
 *	function in the standard library other than the signal function itself or
 *	refers to any object with static storage duration other than by assigning a
 *	value to a static storage duration variable of type volatile sig_atomic_t.
 *	Furthermore, if such a call to the signal function results in a SIG_ERR
 *	return, the value of errno is indeterminate.
 *
 *		At program startup, the equivalent of 
 *
 *			signal(sig, SIG_IGN);
 *
 *	may be executed for some signals selected in an implementation-defined
 *	manner; the equivalent of
 *
 *			signal(sig, SIG_DFL);
 *
 *	is executed for all other signals defined by the implementation.
 *
 *		The implementation shall behave as if no library function calls the
 *	signal function.
 *
 *
 *	Returns
 *
 *		If the request can be honored, the signal function returns the value of
 *	func for the most recent call to signal for the specified signal sig.
 *	Otherwise, a value of SIG_ERR is returned and a positive value is store in
 *	errno.
 */

#include <signal.h>
#include <errno.h>
#include <fcntl.h>

void (*_sigfuns[_NUMSIG])(int);
static char setup;
static void _sig_setup(void);

void (*signal(register int sig, void (*func)(int)))(int)
{
	register void (*retval)(int);

	if (!setup) {
		_sig_setup();
		setup = 1;
	}
	if ((sig -= _FSTSIG) < 0 || sig >= _NUMSIG) {
		errno = EINVAL;
		return SIG_ERR;
	}
	retval = _sigfuns[sig];
	_sigfuns[sig] = func;
	return retval;
}

int
raise(int sig)
{
	register void (*handler)(int);
	register int tsig = sig - _FSTSIG;

	if (tsig < 0 || tsig >= _NUMSIG)
		return(-1);
	if ((handler = _sigfuns[tsig]) == SIG_DFL)
		_exit(255);
	if (handler != SIG_IGN) {
		_sigfuns[tsig] = SIG_DFL;
		(*handler)(sig);
	}
	return(0);
}

#include <exec/types.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#include <functions.h>

extern int _trapintercept;
extern void *_oldtrap, **_trapaddr;

static void
_sig_setup(void)
{
	struct Task *tp;
	extern struct ExecBase *SysBase;

	tp = FindTask(0L);
	_trapaddr = (void *)&tp->tc_TrapCode;
	_oldtrap= tp->tc_TrapCode;
	tp->tc_TrapCode = (APTR)&_trapintercept;
	if (SysBase->AttnFlags & AFF_68881) {
#asm
		mc68881

		fmove.l	FPCR,d0
		or.w	#$1400,d0
		fmove.l	d0,FPCR
#endasm
	}
}

void
_traphand(long code)
{
	if (code == 5 || code == 7 || code == 50 || code == 53)
		raise(SIGFPE);
	else if (code == 2 || code == 3)
		raise(SIGSEGV);
	else if (code == 4)
		raise(SIGILL);
}

#asm
	far		code
	public	_geta4

	public	__trapintercept
__trapintercept:
	movem.l	d0/a4,-(sp)		;need some registers
	jsr		_geta4			;set up a4
	move.l	8(sp),d0		;get trap number
	cmp.w	#50,d0			;is it 881 div0?
	beq		2$				;yes, do it
	cmp.w	#53,d0			;is it 881 overflow
	beq		2$				;yes, do it
	cmp.w	#7,d0			;is it in right range?
	bgt		1$				;no, do default
	cmp.w	#6,d0			;is it CHK
	bne		2$				;no, go handle it
1$:
	move.l	4(sp),d0		;get a4 for later
	move.l	__oldtrap,4(sp)	;get regular handler
	move.l	d0,a4			;set real a4 value
	move.l	(sp)+,d0		;restore d0 contents
	rts						;jump to it

2$:
	move.l	a0,-(sp)		;save a0
	move.l	usp,a0			;get user stack pointer
	move.l	18(sp),-(a0)	;save old pc
	move.w	14(sp),-(a0)	;save old sr
	movem.l	d0-d7/a0-a6,-(a0)	;save old registers
	movem.l	(sp)+,d1/d2/d3	;restore d0/a0/a4
	move.l	d1,(a0)			;set d0
	move.l	d2,32(a0)		;set a0
	move.l	d3,48(a0)		;set a4
	move.l	d0,-(a0)		;pass trap number on stack
	lea		3$,a1			;get return in case they want to continue
	move.l	a1,-(a0)		;set return address
	move.l	a0,usp			;set new user stack pointer
	lea		__traphand,a0	;get trap handler
	move.l	a0,6(sp)		;modify rte address
	add.w	#4,sp			;remove trap #
	rte						;go and do the handler

3$:
	add.w	#4,sp			;pop arg
	movem.l	(sp)+,d0-d7/a0-a6	;restore old registers
	move.w	(sp)+,ccr		;restore old condition codes
	rts						;and continue where we left off

#endasm

tolower.a68
; Copyright 1989 Manx Software Systems, Inc. All rights reserved
; :ts=8

;	Synopsis
;
;	int tolower(int c);
;
;
;	Description
;
;	    The tolower function converts an upper-case letter to the
;	corresponding lower-case letter.
;	
;
;	Returns
;
;	    If the argument is an upper-case letter, the tolower function
;	returns the corresponding lower-case letter if there is one; otherwise
;	the argument is returned unchanged. In the "C" locale, tolower maps
;	only the characters for which isupper is true to the corresponding
;	characters for which islower is true.

;
	public _tolower
;
_tolower
	IF INT32
	move.l	4(sp),d0
	cmp.l	#'A'-1,d0
	bls	tl_done
	cmp.l	#'Z',d0
	bhi	tl_done
	add.l	#'a'-'A',d0
	ELSE
	move.w	4(sp),d0
	cmp.w	#'A'-1,d0
	bls	tl_done
	cmp.w	#'Z',d0
	bhi	tl_done
	add.w	#'a'-'A',d0
	ENDC
tl_done:
	rts

toupper.a68
; Copyright 1989 Manx Software Systems, Inc. All rights reserved
; :ts=8

;	Synopsis
;
;	int toupper(int c);
;
;
;	Description
;
;	    The toupper function converts a lower-case letter to the
;	corresponding upper-case letter.
;	
;
;	Returns
;
;	    If the argument is an lower-case letter, the toupper function
;	returns the corresponding upper-case letter if there is one; otherwise
;	the argument is returned unchanged. In the "C" locale, toupper maps
;	only the characters for which islower is true to the corresponding
;	characters for which isupper is true.

	public _toupper
;
_toupper
	IF INT32
	move.l	4(sp),d0
	cmp.l	#'a'-1,d0
	bls	tu_done
	cmp.l	#'z',d0
	bhi	tu_done
	sub.l	#'a'-'A',d0
	ELSE
	move.w	4(sp),d0
	cmp.w	#'a'-1,d0
	bls	tu_done
	cmp.w	#'z',d0
	bhi	tu_done
	sub.w	#'a'-'A',d0
	ENDC
tu_done:
	rts

