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

;	Synopsis
;
;	char *index(const char *s, int c);
;
;
;	Description
;
;	    The index function locates the first occurrence of c (converted to
;	a char) in the string pointed to by s. The terminating null character
;	is considered to be part of the string.
;
;
;	Returns
;
;	    The index function returns a pointer to the located character, or
;	a null pointer if the character does not occur in the string.


	xref	_strchr

	xdef	_index
_index:
	jmp	_strchr

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

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

CLIB=\
	index.$O  memchr.$O memcmp.$O memcpy.$O memmove.$O \
	memset.$O movmem.$O rindex.$O strcat.$O strchr.$O \
	strcmp.$O strcpy.$O strcspn.$O strerror.$O strlen.$O \
	strncat.$O strncmp.$O strncpy.$O strpbrk.$O strrchr.$O \
	strspn.$O strstr.$O strtok.$O strxfrm.$O swapmem.$O \
	setmem.$O strdup.$O strcoll.$O

clib:	$(CLIB)

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

;	Synopsis
;
;	void *memchr(const void *s, int c, size_t n)
;
;
;	Description
;
;	    The memchr function locates the first occurrence of c (converted to
;	an unsigned char) in the initial n characters (each interpreted as
;	unsigned char) of the object pointed to by s.
;
;
;	Returns
;
;	    The memchr function returns a pointer to the located character, or
;	a null pointer if the character does not occur in the object.

	xdef	_memchr
_memchr:
	move.l	4(sp),a0	;a0 is pointer to memory
	IF INT32
	move.l	12(sp),d0	;d0 is number of characters
	beq	notfound	;return zero if not found
	move.b	11(sp),d1	;get character to search for
	ELSE
	move.l	10(sp),d0	;d0 is number of characters
	beq	notfound	;return zero if not found
	move.b	9(sp),d1	;get character to search for
	ENDC
	sub.l	#1,d0		;decrement for first loop
.1
	cmp.b	(a0)+,d1	;check against character
	dbeq	d0,.1		;loop till match or end of count
	beq	found		;skip if found
	sub.l	#$10000,d0	;loop till high word done
	bpl	.1
notfound:
	move.l	#0,d0		;return 0 if not found in all n bytes
	rts

found:
	sub.w	#1,a0		;back up to character itself
	move.l	a0,d0		;return pointer to character
	rts

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

;	Synopsis
;
;	int memcmp(const void *s1, const void *s2, size_t n);
;
;
;	Description
;
;	    The memcmp function compares the first n characters of the object
;	pointed to by s1 to the first n characters of the object pointed to by
;	s2.
;
;
;	Returns
;
;	    The memcmp function returns an integer greater than, equal to, or
;	less than zero, according as the object pointed to by s1 is greater
;	than, equal to, or less than the object pointed to by s2.

	xdef	_memcmp
_memcmp:
	movem.l	4(sp),a0/a1	;a0 is s1, a1 is s2
	cmp.l	a0,a1
	beq	equalstr	;don't compare if same string
	move.l	12(sp),d1	;get count
	beq	equalstr	;don't compare if count is zero
	sub.l	#1,d1		;decrement for loop
.1
	cmp.b	(a1)+,(a0)+	;compare bytes
	dbne	d1,.1		;loop until mismatch OR n compares made
	bne	notequal	;skip to 
	sub.l	#$10000,d1	;loop till high word done
	bpl	.1
equalstr:
	move.l	#0,d0		;return 0 if equal
	rts

notequal:
	bls	less
	move.l	#1,d0		;return 1 if greater
	rts

less:
	move.l	#-1,d0		;return -1 if less
	rts

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

;	Synopsis
;
;	void *memcpy(void *dst, const void *src, size_t n);
;
;
;	Description
;
;	    The memcpy function copies n characters from the object pointed to
;	by src into the object pointed to by dst. If copying takes place
;	between objects that overlap, the behavior is undefined.
;
;
;	Returns
;
;	    The memcpy function returns the value of dst.

	xdef	_memcpy
_memcpy:
	movem.l	4(sp),a0/a1	;a0 is dest, a1 is src
	move.l	a0,d0		;return dest
	move.l	12(sp),d1	;get count
	bra	.2		;be sure to decrement first
.1
	move.b	(a1)+,(a0)+	;copy byte
.2
	dbra	d1,.1		;loop till done
	sub.l	#$10000,d1	;see if high word done yet
	bpl	.1		;loop till done
	rts

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

;	Synopsis
;
;	void *memmove(void *dst, const void *src, size_t n);
;
;
;	Description
;
;	    The memmove function copies n characters from the object pointed to
;	by src into the object pointed to by dst. Copying takes place as if the
;	n characters from the object pointed to by src are first copied into a
;	temporary array of n characters that does not overlap the objects
;	pointed to by dst and src, and then the n characters from the temporary
;	array are copied into the object pointed to by dst.
;
;
;	Returns
;
;	    The memmove function returns the value of dst.

	xdef _memmove
_memmove:
	movem.l	4(sp),a0/a1	;a0 is dst, a1 is src
	move.l	a0,d0		;return dst
	move.l	12(sp),d1	;get count
	cmp.l	a1,a0		;check for move direction
	beq	.3		;silly to move onto itself
	bls	forward		;start at beginning
	add.l	d1,a0		;else start at end
	add.l	d1,a1
	bra	.2		;skip so decrement first
.1
	move.b	-(a1),-(a0)	;copy byte
.2
	dbra	d1,.1		;loop till done
	sub.l	#$10000,d1	;loop till high word done
	bpl	.2

.3
	rts			;and return
;
.4
	move.b	(a1)+,(a0)+	;copy byte
forward:
	dbra	d1,.4		;loop till done
	sub.l	#$10000,d1	;loop till high word done
	bpl	.4
	rts			;and return

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

;	Synopsis
;
;	void *memset(void *s, int c, size_t n);
;
;
;	Description
;
;	    The memset function copies the value of c (converted to an
;	unsigned char) into each of the first n characters of the object
;	pointed to by s.
;
;
;	Returns
;
;	    The memset function returns the value of s.

	xdef	_memset
_memset:
	move.l	4(sp),a0	;a0 is s
	IF INT32
	movem.l	8(sp),d0/d1	;d0 is c, d1 is n
	ELSE
	move.w	8(sp),d0	;d0 is c
	move.l	10(sp),d1	;d1 is n
	ENDC
	bra	.2		;skip for pre-decrement
.1
	move.b	d0,(a0)+	;store value and bump pointer
.2
	dbra	d1,.1		;loop for n values
	sub.l	#$10000,d1	;loop for high part of n
	bpl	.1
	move.l	4(sp),d0	;return s
	rts

movmem.a68
; Copyright 1989 by Manx Software Systems, Inc.
; :ts=8

;	Synopsis
;
;	void movmem(const void *src, void *dst, size_t n);
;
;
;	Description
;
;	    The movmem function copies n characters from the object pointed to
;	by src into the object pointed to by dst. Copying takes place as if the
;	n characters from the object pointed to by src are first copied into a
;	temporary array of n characters that does not overlap the objects
;	pointed to by dst and src, and then the n characters from the temporary
;	array are copied into the object pointed to by dst.
;
;
;	Returns
;
;	    The movmem function returns no value.


	xdef _movmem
_movmem:
	movem.l	4(sp),a0/a1	;a0 is src, a1 is dst

	IF INT32
	move.l	12(sp),d1	;get count
	ELSE
	move.l	#0,d1		;always a long in case we add
	move.w	12(sp),d1
	ENDC

	cmp.l	a0,a1		;check for move direction
	beq	.3		;silly to move onto itself
	bls	forward		;start at beginning
	add.l	d1,a1		;else start at end
	add.l	d1,a0
	bra	.2		;skip so decrement first
.1
	move.b	-(a0),-(a1)	;copy byte
.2
	dbra	d1,.1		;loop till done

	IF INT32
	sub.l	#$10000,d1	;loop till high word done
	bpl	.2
	ENDC

.3
	rts			;and return

.4
	move.b	(a0)+,(a1)+	;copy byte
forward:
	dbra	d1,.4		;loop till done

	IF INT32
	sub.l	#$10000,d1	;loop till high word done
	bpl	.4
	ENDC

	rts			;and return

rindex.a68
; Copyright 1989 Manx Software Systems, Inc
; :ts=8

;	Synopsis
;
;	char *rindex(const char *s, int c);
;
;
;	Description
;
;	    The rindex function locates the last occurrence of c (converted to
;	a char) in the string pointed to by s. The terminating null character
;	is considered to be part of the string.
;
;
;	Returns
;
;	    The rindex function returns a pointer to the character, or a null
;	pointer if c does not occur in the string.

	xref	_strrchr

	xdef	_rindex
_rindex:
	jmp	_strrchr

setmem.a68
; Copyright 1989 Manx Software Systems, Inc
; :ts=8

;	Synopsis
;
;	void setmem(void *s, size_t n, int c);
;
;
;	Description
;
;	    The setmem function copies the value of c (converted to an
;	unsigned char) into each of the first n characters of the object
;	pointed to by s.
;
;
;	Returns
;
;	    The setmem function returns no value.

	xdef	_setmem
_setmem:
	move.l	4(sp),a0	;a0 is s

	IF INT32
	movem.l	8(sp),d0/d1	;d0 is n, d1 is c
	ELSE
	movem.w	8(sp),d0/d1
	ENDC

	bra	.2		;skip for pre-decrement
.1
	move.b	d1,(a0)+	;store value and bump pointer
.2
	dbra	d0,.1		;loop for n values

	IF INT32
	sub.l	#$10000,d0	;loop for high part of n
	bpl	.1
	ENDC

	rts

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

;	Synopsis
;
;	char *strcat(char *dst, const char *src)
;
;
;	Description
;
;	    The strcat function appends a copy of the string pointed to by src
;	(including the terminating null character) to the end of the string
;	pointed to by dst. The initial character of src overwrites the null
;	character at the end of dst. If copying takes place between objects
;	that overlap, the behavior is undefined.
;
;
;	Returns
;
;	    The strcat function returns the value of dst.

	xdef	_strcat
_strcat:
	movem.l	4(sp),a0/a1	;a0 is dst, a1 is src
	move.l	a0,d0		;return dst
.1
	tst.b	(a0)+		;skip to end of dst
	bne	.1
	sub.w	#1,a0		;back up to null
.2
	move.b	(a1)+,(a0)+	;copy src
	bne	.2		;till null
	rts			;and return

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

;	Synopsis
;
;	char *strchr(const char *s, int c);
;
;
;	Description
;
;	    The strchr function locates the first occurrence of c (converted to
;	a char) in the string pointed to by s. The terminating null character
;	is considered to be part of the string.
;
;
;	Returns
;
;	    The strchr function returns a pointer to the located character, or
;	a null pointer if the character does not occur in the string.

	xdef	_strchr
_strchr:
	move.l	4(sp),a0	;get string pointer
	move.l	#0,d0		;needed to make dbeq loop work

	IF INT32
	move.b	11(sp),d1	;get character to look for
	ELSE
	move.b	9(sp),d1
	ENDC

.1
	move.b	(a0)+,d0	;get next character in string
	cmp.b	d1,d0		;see if matches one we want
	dbeq	d0,.1		;loop while not a match and d0 not zero
	beq	.2		;if equal, found character
	move.l	#0,d0		;d0 was zero, ie. end of string, so no match
	rts
.2
	sub.w	#1,a0		;back up to matched character
	move.l	a0,d0		;copy to d0 for return
	rts

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

;	Synopsis
;
;	int strcmp(const char *s1, const char *s2);
;
;
;	Description
;
;	    The strcmp function compares the string pointed to by s1 to the
;	string pointed to by s2.
;
;
;	Returns
;
;	    The strcmp function returns an integer greater than, equal to, or
;	less than zero, according as the string pointed to by s1 is greater
;	than, equal to, or less than the string pointed to by s2.

	xdef	_strcmp
_strcmp:	
	movem.l	4(sp),a0/a1	;a0 is s1, a1 is s2
	cmp.l	a0,a1
	beq	equal		;if strings are the same, must be equal
	move.l	#0,d0		;needed to make tricky dbne loop work.
.1
	move.b	(a0)+,d0	;pick up first byte
	cmp.b	(a1)+,d0	;compare to second
	dbne	d0,.1		;if both are same and first is not 0, loop
	bne	notequal	;if both are not same, set result
equal:
	move.l	#0,d0		;return 0 if strings match
	rts

notequal:
	bls	less
	move.l	#1,d0		;return 1 if greater
	rts

less:
	move.l	#-1,d0		;return -1 if less
	rts

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

;	Synopsis
;
;	int strcoll(const char *s1, const char *s2);
;
;
;	Description
;
;	    The strcoll function compares the string pointed to by s1 to the
;	string pointed to by s2, both interpreted as appropriate to the
;	LC_COLLATE category of the current locale.
;
;
;	Returns
;
;	    The strcoll function returns an integer greater than, equal to, or
;	less than zero, according as the string pointed to by s1 is greater
;	than, equal to, or less than the string pointed to by s2 when both are
;	interpreted as appropriate to the current locale.

	xdef	_strcoll
_strcoll:	
	movem.l	4(sp),a0/a1	;a0 is s1, a1 is s2
	cmp.l	a0,a1
	beq	equal		;if strings are the same, must be equal
	move.l	#0,d0		;needed to make tricky dbne loop work.
.1
	move.b	(a0)+,d0	;pick up first byte
	cmp.b	(a1)+,d0	;compare to second
	dbne	d0,.1		;if both are same and first is not 0, loop
	bne	notequal	;if both are not same, set result
equal:
	move.l	#0,d0		;return 0 if strings match
	rts

notequal:
	bls	less
	move.l	#1,d0		;return 1 if greater
	rts

less:
	move.l	#-1,d0		;return -1 if less
	rts

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

;	Synopsis
;
;	char *strcpy(char *dst, const char *src)
;
;
;	Description
;
;	    The strcpy function copies the string pointed by src (including the
;	terminating null character) into the array pointed to by dst. If
;	copying takes place between objects that overlap, the behavior is
;	undefined.
;
;
;	Returns
;
;	    The strcpy function returns the value of dst.

	xdef	_strcpy
_strcpy:
	movem.l	4(sp),a0/a1	;dst in a0, src in a1
	move.l	a0,d0		;return dst
.1
	move.b	(a1)+,(a0)+	;copy byte
	bne.s	.1		;loop till null
	rts			;and return

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

;	Synopsis
;
;	size_t strcspn(const char *s1, const char *s2);
;
;
;	Description
;
;	    The strcspn function computes the length of the maximum initial
;	segment of the string pointed to by s1 which consists entirely of
;	characters NOT from the string pointed to by s2.
;
;
;	Returns
;
;	    The strcspn function returns the length of the segment.

	xdef	_strcspn
_strcspn:
	movem.l	d2/d3,-(sp)	;save d2 and d3
	movem.l	12(sp),d2/d3	;d2 is s1, d3 is s2
	move.l	d2,a0		;a0 is s1
.1
	move.b	(a0)+,d0	;get next character from s1
	beq	.3		;exit if null
	move.l	d3,a1		;get pointer to s2
.2
	move.b	(a1)+,d1	;get next character from s2
	beq	.1		;loop back if at end of s2
	cmp.b	d0,d1		;see if matches one we want
	bne	.2		;loop till done or we have a match
.3
	sub.w	#1,a0		;back up to previously unmatched character
	move.l	a0,d0		;copy for return
	sub.l	d2,d0		;compute length
	movem.l	(sp)+,d2/d3	;restore registers
	rts			;return length

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

;	Synopsis
;
;	char *strdup(const char *s);
;
;
;	Description
;
;	    The strdup function makes a copy of the string pointed to by s. The
;	space for the copy is allocated using the malloc function.
;
;
;	Returns
;
;	    The strdup function returns a pointer to the array allocated. If
;	the array could not be allocated, a null pointer is returned.

	xref	_malloc

	xdef	_strdup
_strdup:
	move.l	4(sp),a0
	move.l	a0,d0
.1	tst.b	(a0)+
	bne.s	.1
	sub.l	d0,a0
	move.l	a0,-(sp)
	jsr	_malloc
	add.w	#4,sp
	tst.l	d0
	beq	.3
	move.l	d0,a0
	move.l	4(sp),a1
.2	move.b	(a1)+,(a0)+
	bne.s	.2
.3
	rts

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

/*
 *	Synopsis
 *
 *	char *strerror(int errnum);
 *
 *
 *	Description
 *
 *	    The strerror function maps the error number in errnum to an error
 *	message string.
 *
 *		The implementation shall behave as if no library function calls the
 *	strerror function.
 *
 *
 *	Returns
 *
 *		The strerror function returns a pointer to the string, the contents of
 *	which are implementation-defined. The array pointed to shall not be
 *	modified by the program, but may be overwritten by a subsequent call to the
 *	strerror function.
 */

#include <errno.h>
#include <stdlib.h>

char *sys_errlist[] = {
/* 0		*/	"",
/* ENOENT	*/	"No such file or directory",
/* E2BIG	*/	"Arg list too long",
/* EBADF	*/	"Bad file descriptor",
/* ENOMEM	*/	"Not enough memory",
/* EEXIST	*/	"File exists",
/* EINVAL	*/	"Invalid argument",
/* ENFILE	*/	"File table overflow",
/* EMFILE	*/	"Too many open files",
/* ENOTTY	*/	"Not a console",
/* EACCES	*/	"Permission denied",
/* EIO		*/	"I/O error",
/* ENOSPC	*/	"No space left on device",
/* ERANGE	*/	"Result too large",
/* EDOM		*/	"Argument out of domain",
/* ENOEXEC	*/	"Exec format error",
/* EROFS	*/	"Read-only file system",
/* EXDEV	*/	"Cross-device rename",
/* EAGAIN	*/	"Nothing to read",
};

int	sys_nerr = { sizeof(sys_errlist)/sizeof(sys_errlist[0]) };
#define LERRNO EAGAIN

char *
strerror(register int errnum)
{
	if (errnum >= 0 && errnum <= LERRNO)
		return(sys_errlist[errnum]);
	return("Unknown error");
}

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

;	Synopsis
;
;	size_t strlen(const char *s);
;
;
;	Description
;
;	    The strlen function computes the length of the string pointed to
;	by s.
;
;
;	Returns
;
;	    The strlen function returns the number of characters that precede
;	the terminating null character.

	xdef	_strlen
_strlen:
	move.l	4(sp),a0	;a0 is s
	move.l	a0,d0		;save s for later calculation
.1
	tst.b	(a0)+		;skip till reach end of string
	bne	.1
	sub.w	#1,a0		;back up to null
	sub.l	d0,a0		;compute length from start
	move.l	a0,d0		;put in d0 for return
	rts
;
strncat.a68
; Copyright 1989 Manx Software Systems, Inc. All rights reserved
; :ts=8

;	Synopsis
;
;	char *strncat(char *dst, const char *src, size_t n)
;
;
;	Description
;
;	    The strncat function appends not more than n characters (a null
;	character and characters that follow it are not appended) from the
;	array pointed to by src to the end of the string pointed to by dst. The
;	initial character of src overwrites the null character at the end of
;	dst. A terminating null character is always appended to the result. If
;	copying takes place between objects that overlap, the behavior is
;	undefined.
;
;
;	Returns
;
;	    The strncat function returns the value of dst.

	xdef	_strncat
_strncat:
	movem.l	4(sp),a0/a1	;a0 is dst, a1 is src
	move.l	a0,d0		;return dst
	move.l	12(sp),d1	;get count
.1
	tst.b	(a0)+		;skip to end of dst
	bne	.1
	subq.l	#1,a0		;back up to null
.2
	move.b	(a1)+,(a0)+	;copy from src
	dbeq	d1,.2		;loop till done or null
	sub.l	#$10000,d1	;loop till high word done
	bpl	.2
	clr.b	-(a0)		;back up to n'th byte and clear
	rts			;and return

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

;	Synopsis
;
;	int strncmp(const char *s1, const char *s2, size_t n);
;
;
;	Description
;
;	    The strncmp function compares not more than n characters
;	(characters that follow a null character are not compared) from the
;	array pointed to by s1 to the array pointed to by s2.
;
;
;	Returns
;
;	    The strncmp function returns an integer greater than, equal to, or
;	less than zero, according as the possibly null-terminated array pointed
;	to by s1 is greater than, equal to, or less than the possibly
;	null-terminated array pointed to by s2.


	xdef	_strncmp
_strncmp
	movem.l	4(sp),a0/a1	;a0 is s1, a1 is s2
	cmp.l	a0,a1
	beq	equal		;skip if same string
	move.l	12(sp),d1	;get count
	beq	equal		;skip if nothing to compare
	sub.l	#1,d1		;decrement for later loop
.1
	move.b	(a0)+,d0	;get the next s1 byte
	cmp.b	(a1)+,d0	;compare to next s2 byte
	bne	notequal	;skip if not same
	tst.b	d0		;see if both were null
	dbeq	d1,.1		;if not null or more bytes, loop
	sub.l	#$10000,d1	;loop till high word done
	bpl	.1
equal:
	move.l	#0,d0		;always return zero if equal
	rts

notequal:
	bls	less
	move.l	#1,d0		;return 1 if greater
	rts

less:
	move.l	#-1,d0		;return -1 if less
	rts

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

;	Synopsis
;
;	char *strncpy(char *dst, const char *src, size_t n)
;
;
;	Description
;
;	    The strncpy function copies not more than n characters (characters
;	that follow a null character are not copied) from the array pointed to
;	by src to the array pointed to by dst. If copying takes place between
;	objects that overlap, the behavior is undefined.
;
;	    If the array pointed to by src is a string that is shorter than n
;	characters, null characters are appended to the copy in the array
;	pointed to by dst, until n characters have been written.
;
;
;	Returns
;
;	    The strncpy function returns the value dst.

	xdef	_strncpy
_strncpy
	movem.l	4(sp),a0/a1	;a0 is dst, a1 is src
	move.l	a0,d0		;return dst
	move.l	12(sp),d1	;get count
	bra	.2		;decrement first
.1
	move.b	(a1)+,(a0)+	;copy byte
.2
	dbeq	d1,.1		;loop till done or null
	beq	.4		;if null, pad the rest, decrement first
	sub.l	#$10000,d1	;loop till done
	bpl	.1
	rts			;and return

.3
	clr.b	(a0)+		;clear bytes
.4
	dbra	d1,.3		;loop till done
	sub.l	#$10000,d1	;loop till done
	bpl	.3
	rts			;and return

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

;	Synopsis
;
;	char *strpbrk(const char *s1, const char *s2);
;
;
;	Description
;
;	    The strpbrk function locates the first occurrence in the string
;	pointed to by s1 of any character from the string pointed to by s2.
;
;
;	Returns
;
;	    The strpbrk function returns a pointer to the character, or a null
;	pointer if no character from s2 occurs in s1.

	xdef	_strpbrk
_strpbrk:
	move.l	d2,-(sp)	;save register
	movem.l	8(sp),a0/a1	;a0 is s1, a1 is s2
	move.l	a1,d2		;make copy of s2
.1
	move.b	(a0)+,d1  	;get next character from s1
	beq	.3		;done if at end of s1 without a match
	move.l	d2,a1		;get pointer to s2
.2
	move.b	(a1)+,d0	;get next character from s2
	beq	.1		;loop if at end of s2 without a match
	cmp.b	d1,d0		;does this char from s2 match char from s1
	bne	.2		;no, try next

	move.l	(sp)+,d2	;restore register
	sub.w	#1,a0		;match, back up to it
	move.l	a0,d0		;and copy to d0 for return
	rts
.3
	move.l	(sp)+,d2	;restore register
	move.l	#0,d0		;return zero if not found
	rts

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

;	Synopsis
;
;	char *strrchr(const char *s, int c);
;
;
;	Description
;
;	    The strrchr function locates the last occurrence of c (converted to
;	a char) in the string pointed to by s. The terminating null character
;	is considered to be part of the string.
;
;
;	Returns
;
;	    The strrchr function returns a pointer to the character, or a null
;	pointer if c does not occur in the string.

	xdef	_strrchr
_strrchr:
	move.l	4(sp),a0	;a0 is pointer to string
	move.l	a0,a1		;make a copy
.1
	tst.b	(a0)+		;test for null byte at end of string
	bne	.1		;loop till found, a0 points at null + 1

	IF INT32
	move.b	11(sp),d0	;get character to search for
	ELSE
	move.b	9(sp),d0
	ENDC

.2
	cmp.l	a0,a1		;compare to original pointer
	beq	.3		;if at beginning, no match
	cmp.b	-(a0),d0	;back up and compare to character
	bne	.2		;loop if not found
	move.l	a0,d0		;found, return pointer
	rts
.3
	move.l	#0,d0		;not found, return null pointer
	rts

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

;	Synopsis
;
;	size_t strspn(const char *s1, const char *s2);
;
;
;	Description
;
;	    The strspn function computes the length of the maximum initial
;	segment of the string pointed to by s1 which consists entirely of
;	characters from the string pointed to by s2.
;
;
;	Returns
;
;	    The strspn function returns the length of the segment.

	xdef	_strspn
_strspn:
	move.l	a2,-(sp)	;save register
	movem.l	8(sp),a0/a1	;a0 is s1, a1 is s2
	bra	.3		;skip to end of loop
.1
	move.l	a1,a2		;get pointer to s2
.2
	move.b	(a2)+,d1	;get next char from s2
	beq	.4		;if null, no match, so go calc length
	cmp.b	d0,d1		;else compare to char from s1
	bne	.2		;if no match, keep checking s2 chars
.3
	move.b	(a0)+,d0	;get next char from s1
	bne	.1		;continue while chars remain from s1
.4
	sub.l	#1,a0		;correct for autoincrement of a0
	move.l	a0,d0		;copy to d0 for return
	sub.l	8(sp),d0	;compute length
	move.l	(sp)+,a2	;restore register
	rts

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

;	Synopsis
;
;	char *strstr(const char *s1, const char *s2);
;
;
;	Description
;
;	    The strstr function locates the first occurrence in the string
;	pointed to by s1 of the sequence of characters (excluding the
;	terminating null character) of the string pointed to by s2.
;
;
;	Returns
;
;	    The strstr function returns a pointer to the located string, or a
;	null pointer if the string is not found.  If s2 points to a string with
;	zero length, the function returns s1.

	xdef	_strstr
_strstr:
	move.l	a2,-(sp)	;save register
	movem.l	8(sp),a0/a1	;a0 is s1, a1 is s2
	move.l	a1,d0		;now, d0 is s2
.1
	move.l	a0,a1		;a1 is pointer into s1
	move.l	d0,a2		;a2 is pointer to s2
.2
	move.b	(a2)+,d1	;get next character in s2
	beq	success		;if at end of s2, we have a match
	cmp.b	(a1)+,d1	;else, check against next char in s1
	beq	.2		;if match, continue through s2
	tst.b	(a0)+		;else start to next char in s1
	bne	.1		;if not at end of s1, start check over again
	move.l	#0,a0		;if at end of s1, then no match, return zero
success:
	move.l	a0,d0		;return position in s1 where s2 starts
	move.l	(sp)+,a2	;restore register
	rts

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

;	Synopsis
;
;	char *strtok(char *s1, const char *s2);
;
;
;	Description
;
;	    A sequence of calls to the strtok function breaks the string
;	pointed to by s1 into a sequence of tokens, each of which is delimited
;	by a character from the string pointed to by s2.  The first call in the
;	sequence has s1 as its first argument, and is followed by calls with
;	a null pointer as their first argument. The separator string pointed
;	to by s2 may be different from call to call.
;
;	    The first call in the sequence searches the string pointed to by s1
;	for the first character that is NOT contained in the current
;	separator string pointed to by s2. If no such character is found,
;	then there are no tokens in the string pointed to by s1 and the
;	strtok function returns a null pointer.  If such a character is found,
;	it is the start of the first token.
;
;	    The strtok function then searches from there for a character that
;	IS contained in the current separator string.  If no such character is
;	found, the current token extends to the end of the string pointed to
;	by s1, and subsequent searches for a token will return a null pointer.
;	If such a char is found, it is overwritten by a null character, which
;	terminates the current token. The strtok function saves a pointer to
;	the following character, from which the next search for a token will
;	start.
;
;	    Each subsequent call, with a null pointer as the value of the
;	first, argument, starts searching from the saved pointer and behaves as
;	described above.
;
;
;	Returns
;
;	    The strtok function returns a pointer to the first character of a
;	token, or a null pointer if there is no token.

	bss	save_ptr,4

	xref	_strspn
	xref	_strpbrk

	xdef	_strtok
_strtok:
	movem.l	4(sp),a0/a1	;a0 is s1, a1 is s2
	move.l	a0,d0		;check if null
	bne	mainline	;no, skip to mainline
	move.l	save_ptr,a0	;else get saved pointer
	tst.b	(a0)		;see if at end of string
	bne	mainline	;no, skip to mainline
nomore
	move.l	#0,d0		;no more tokens, return null pointer
	rts

mainline
	movem.l	a0/a1,-(sp)	;save pointers
	movem.l	a0/a1,-(sp)	;push args
	jsr	_strspn		;skip the leading separators
	add.w	#8,sp		;pop args
	movem.l	(sp)+,a0/a1	;restore pointers
	add.w	d0,a0		;pointer += strspn(pointer, s2);
	tst.b	(a0)
	beq	nomore		;if at end of string, no more tokens
skip
	move.l	a0,-(sp)		;save pointer to token
	movem.l	a0/a1,-(sp)	;push args
	jsr	_strpbrk	;search for char that IS contained in s2
	add.w	#8,sp		;pop args
	tst.l	d0		;check return
	beq	return		;couldn't find, token is rest of string

	move.l	d0,a0		;copy to a0
	clr.b	(a0)		;write null character
	add.l	#1,d0		;skip past null for next call
return
	move.l	d0,save_ptr	;save pointer for next call
	move.l	(sp)+,d0	;return pointer to 1st char of token
	rts

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

;	Synopsis
;
;	size_t strxfrm(char *dst, const char *src, size_t n);
;
;
;	Description
;
;	    The strxfrm function transforms the string pointed to by src and
;	places the resulting string into the array pointed to by dst. The
;	transformation is such that if the strcmp function is applied to two
;	transformed strings, it returns a value greater than, equal to, or less
;	than zero, corresponding to the result of the strcoll function applied
;	to the same two original strings. No more than n characters are
;	placed into the resulting array pointed to by dst, including the
;	terminating null character. If n is zero, dst is permitted to be
;	a null pointer. If copying takes place between objects that overlap,
;	the behavior is undefined.
;
;
;	Returns
;
;	    The strxfrm function returns the length of the transformed string
;	(not including the terminating null character). If the value returned
;	is n or more, the contents of the array pointed to by dst are
;	indeterminate.

	xref	_strncpy
	xref	_strlen

	xdef	_strxfrm
_strxfrm:
	movem.l	4(sp),a0/a1	;a0 is dst, a1 is src
	move.l	a0,d0		;check for null pointer argument
	beq	.1		;skip to length check
	move.l	12(sp),-(sp)	;push length
	movem.l	a0/a1,-(sp)	;push argument pointers
	jsr	_strncpy	;copy string
	add.w	#12,sp		;pop arguments
.1
	move.l	8(sp),-(sp)	;push src
	jsr	_strlen		;get length
	add.w	#4,sp		;pop argument
	rts			;return length

swapmem.a68
; Copyright 1989 by Manx Software Systems, Inc.
; :ts=8

;	Synopsis
;
;	void swapmem(void *s1, void *s2, size_t n);
;
;
;	Description
;
;	    The swapmem function swaps n characters between the object pointed
;	to by s1 and the object pointed to by s2. If swapping takes place
;	between objects that overlap, the behavior is undefined.
;
;
;	Returns
;
;	    The swapmem function returns no value.


	xdef	_swapmem
_swapmem:
	movem.l	4(sp),a0/a1	;a0 is s1, a1 is s2
	move.l	12(sp),d0	;get count
	bra	.2		;skip for pre-decrement
.1
	move.b	(a0),d1		;get byte in s1
	move.b	(a1),(a0)+	;copy byte from s2 to s1
	move.b	d1,(a1)+	;copy byte from s1 to s2
.2
	dbra	d0,.1		;loop till done
	sub.l	#$10000,d0	;loop till high word done
	bpl	.1
	rts

