[comp.sources.amiga] v90i197: ls 4.0k - yet another unix-like ls command, Part03/04

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (07/04/90)

Submitted-by: kim@uts.amdahl.com (Kim E. DeVaughn)
Posting-number: Volume 90, Issue 197
Archive-name: unix/ls-4.0k/part03

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 4)."
# Contents:  src/lssup.a
# Wrapped by tadguy@xanth on Tue Jul  3 15:22:13 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/lssup.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/lssup.a'\"
else
echo shar: Extracting \"'src/lssup.a'\" \(34948 characters\)
sed "s/^X//" >'src/lssup.a' <<'END_OF_FILE'
X* --------------------------------------------------------------------- *
X* lssup.a - Assembly support routines for ls.c
X* Written by Justin V. McCormick 89-07-24
X* Modified for use in v4.0k by Kim E. DeVaughn - 05/11/90
X* --------------------------------------------------------------------- *
X	IFD	CAPE
X	CSYMFMT
X	BASEREG B
X	SMALLOBJ
X	ADDSYM
X	OPTIMON
X	IDNT	"lssup.a"
X	ENDC
X
X
XSYS	MACRO	*
X	IFGT	NARG-2
X	FAIL	!!!
X	ENDC
X	IFEQ	NARG-2
X	MOVE.L	\2,a6
X	ENDC
X	JSR	LVO\1(a6)
X	ENDM
X
XXLVO	MACRO	*
X	XREF	LVO\1
X	ENDM
X
X; Equates
Xfib_DiskKey	    EQU    $0
Xfib_DirEntryType    EQU    $4
Xfib_FileName	    EQU     $8
Xfib_Size	    EQU     $7C
Xfib_NumBlocks	    EQU     $80
Xfib_DateStamp	    EQU     $84
Xfib_SIZEOF	    EQU     $104
X
Xds_Days 	    EQU     $0
Xds_Minute	    EQU     $4
Xds_Tick 	    EQU     $8
X
XLH_HEAD 	    EQU     $0
XLN_PRED 	    EQU     $4
XLN_SUCC 	    EQU     $0
X
Xfe_Node 	    EQU     $0
Xfe_Fib		    EQU     $8
X
Xpr_ConsoleTask	    EQU     $A4
X
XMEMF_CLEAR	    EQU     $10000
Xsp_Msg		    EQU     $0
Xsp_Pkt		    EQU     $14
Xsp_SIZEOF	    EQU     $44
Xdp_Link 	    EQU     $0
Xdp_Port 	    EQU     $4
Xdp_Arg1 	    EQU     $14
Xdp_Type 	    EQU     $8
XACTION_SCREEN_MODE  EQU     $3E2
XLN_NAME 	    EQU     $A
XLN_PRI		    EQU     $9
XLN_TYPE 	    EQU     $8
XMP_FLAGS	    EQU     $E
XMP_MSGLIST	    EQU     $14
XMP_SIGBIT	    EQU     $F
XMP_SIGTASK	    EQU     $10
XMP_SIZE 	    EQU     $22
XNT_MSGPORT	    EQU     $4
XPA_SIGNAL	    EQU     $0
X
X* Library offsets
X	XLVO	AddPort
X	XLVO	AddTail
X	XLVO	AllocMem
X	XLVO	AllocSignal
X	XLVO	CopyMem
X	XLVO	Debug
X	XLVO	Examine
X	XLVO	FindTask
X	XLVO	FreeMem
X	XLVO	FreeSignal
X	XLVO	GetMsg
X	XLVO	Input
X	XLVO	Insert
X	XLVO	IsInteractive
X	XLVO	Output
X	XLVO	ParentDir
X	XLVO	PutMsg
X	XLVO	RawDoFmt
X	XLVO	Read
X	XLVO	RemPort
X	XLVO	WaitForChar
X	XLVO	WaitPort
X	XLVO	Write
X	XLVO	UnLock
X
X* External constants
X	XREF	@AllocFib
X	XREF	@stpcpy
X	XREF	@strcat
X	XREF	@strlen
X	XREF	baddatestr
X	XREF	badtimestr
X	XREF	ColonStr
X	XREF	datepat
X	XREF	dayspermonth
X	XREF	DOSBase
X	XREF	gwbrstr
X	XREF	LSFlags
X	XREF	RamNameStr
X	XREF	SlashStr
X	XREF	sortkey
X	XREF	timepat
X
X	SECTION CODE
X* --------------------------------------------------------------------- *
X* VOID *myalloc (LONG)
X*   d0		  d0
X* --------------------------------------------------------------------- *
X	XDEF	@myalloc
X@myalloc:
X	movem.l d2/a6,-(sp)
X	addq.l	#4,d0			;Include sizeof(LONG)
X	move.l	d0,d2			;Copy to survive AllocMem
X	moveq	#0,d1			;MEMF_ANYTHING
X	SYS	AllocMem,4		;AllocMem(size + 4, 0L)
X	tst.l	d0			;Got it?
X	 beq.s	1$
X	movea.l d0,a6			;Copy pointer
X	move.l	d2,(a6)+                ;Stash size in first 4 bytes
X	move.l	a6,d0			;return final pointer in d0
X1$
X	movem.l (sp)+,d2/a6
X	rts
X
X* --------------------------------------------------------------------- *
X* VOID myfree (VOID *)
X*		a0
X* --------------------------------------------------------------------- *
X	XDEF	@myfree
X@myfree:
X	move.l	a6,-(sp)
X
X	lea	-4(a0),a1               ;Put in sys reg
X	move.l	(a1),d0                 ;d0 = size to free
X	SYS	FreeMem,4
X
X	movea.l (sp)+,a6
X	rts
X
X* --------------------------------------------------------------------- *
X* void asprintf(wstr, formatstring, args)
X*   char *wstr;
X*   char *formatstring;
X*   char **args;
X*
X* Synopsis: Given formatstring and args to format, formats output to wstr.
X* Similar to sprintf(), except doesn't handle floats.
X* --------------------------------------------------------------------- *
X	XDEF	asprintf
Xasprintf:
X	link	a5,#0
X	movem.l d0-d2/a0-a3/a6,-(sp)    ;Save everything we might clobber
X
X* Call format function to convert fmtstring and args to buffer on the stack
X	movea.l 12(a5),a0               ;Grab format string
X	lea	16(a5),a1               ;Grab EA of arguments
X	lea	kput1,a2		;Grab EA of output subroutine
X	movea.l 8(a5),a3                ;Grab EA of dest workspace
X	SYS	RawDoFmt,4		;Format it into workspace
X
X	movem.l (sp)+,d0-d2/a0-a3/a6    ;Restore registers
X	unlk	a5			;And stack frame
X	rts
X
X* --------------------------------------------------------------------- *
X* RawDoFmt() output routine for xprintf, called for each formatted char.
X* Takes byte in d0 and puts in buffer pointed to by a3, then increments a3.
X* --------------------------------------------------------------------- *
X	XDEF	kput1
Xkput1:
X	move.b	d0,(a3)+
X	rts
X
X* --------------------------------------------------------------------- *
X* void GetWinBounds(width, height)
X*   long *width, *height;
X*	   a0	    a1
X* Find current console window, determine width and height
X* in terms of current font, update width and height VPARMS passed.
X* --------------------------------------------------------------------- *
Xheight	EQU	-4
Xwidth	EQU	-8
Xconid	EQU	-12
Xpacket	EQU	-16
Xrpport	EQU	-20
Xrpstr	EQU	-40
X
X	XDEF	@GetWinBounds
X@GetWinBounds:
X	link	a5,#-44
X	movem.l d2-d4/a2/a6,-(sp)
X
X	move.l	a0,width(a5)            ;Save width/height pointers on stack
X	move.l	a1,height(a5)
X
X	SYS	Input,DOSBase(a4)       ;Grab Input filehandle
X	move.l	d0,d1
X	SYS	IsInteractive		;IsInteractive(Input())?
X	tst.l	d0
X	 beq.s	gwbnowbrep		;Nope, can't get a bounds report
X	SYS	Output
X	move.l	d0,d1
X	SYS	IsInteractive		;IsInteractive(Output())?
X	tst.l	d0
X	 beq.s	gwbnowbrep		;Nope, don't clutter output stream
X
X	suba.l	a1,a1
X	SYS	FindTask,4		;d0 = FindTask(0L), our process
X	movea.l d0,a0			;Transfer to address reg
X	move.l	pr_ConsoleTask(a0),conid(a5) ;Save proc->pr_ConsoleTask
X	tst.l	conid(a5)               ;Is there really a console there?
X	 bne.s	gwbgotcon		;Yep
X
Xgwbnowbrep:
X* Else we cannot get a window bounds report from this source
X	moveq	#23,d1			;return H=23
X	moveq	#77,d2			;	W=77
X	bra	gwbupdate
X
Xgwbgotcon:
X	moveq	#0,d4			;Clear our success status register
X
X	moveq	#0,d0
X	movea.l d0,a0
X	jsr	CreatePort
X	move.l	d0,rpport(a5)           ;rpport = CreatePort(0L, 0L)
X	 beq	gwbdone 		;Oops, no signals or ram available!
X	moveq	#sp_SIZEOF,d0
X	jsr	@myalloc
X	move.l	d0,packet(a5)           ;packet = AllocBlock(sizeof(*packet))
X	 beq	gwbfreeport		;Oops, no ram, free up port
X
X* Okay, we got our process id, reply port, and packet
X* Now toggle the console into raw mode
X	movea.l rpport(a5),a2
X	movea.l d0,a1
X	movea.l conid(a5),a0
X	moveq	#1,d0
X	jsr	SetConsoleType		;SetConsoleType(1L, conid, packet, rpport)
X
X* Request a window bounds report
X	SYS	Output,DOSBase(a4)
X	move.l	d0,d1
X	moveq	#4,d3
X	lea	gwbrstr(a4),a0
X	move.l	a0,d2
X	SYS	Write,DOSBase(a4)       ;Write(Output(), "\2330 q", 4L);
X	cmpi.l	#$0004,d0		;Did the console choke on it?
X	 bne	gwbsetcook		;hmmm, see if we can back out gracefully
X
X* Read the report string into stack buffer, if there is one
X	move.l	#10000,d2
X	SYS	Input
X	move.l	d0,d1
X	SYS	WaitForChar		;WaitForChar(Input(), 10000L) (.01 secs)
X	tst.l	d0			;Did we get the report?
X	 beq	gwbsetcook		;Nope, must not be a report coming
X
X	SYS	Input
X	move.l	d0,d1
X	moveq	#16,d3			;Don't let it get longer than 16 characters
X	lea	rpstr(a5),a0            ;Point to input string area
X	move.l	a0,d2
X	SYS	Read			;Read(Input(), rpstr, 16L)
X	move.l	d0,d4			;Save read length while we close shop
X
X* Turn the console back to cooked mode pronto to avoid cursor blink
Xgwbsetcook:
X	movea.l rpport(a5),a2
X	movea.l packet(a5),a1
X	movea.l conid(a5),a0
X	moveq	#0,d0
X	jsr	SetConsoleType		;SetConsoleType(0L, conid, packet, rpport)
X
X* Release resources we borrowed
Xgwbfreepack:
X	move.l	packet(a5),d0           ;Did we allocate a packet?
X	 beq.s	gwbfreeport		;nay, check for port to free
X	movea.l d0,a0
X	jsr	@myfree 		;Else FreeBlock(packet)
X
Xgwbfreeport:
X	move.l	rpport(a5),d0           ;if (rpport)...
X	 beq	gwbdone 		;nope
X	jsr	DeletePort		;Else DeletePort(rpport)
X
X* Finally, sanity check window bounds report string
X* d4 = length of report string according to Read()
X	cmpi.l	#9,d4			;Less than 8 characters returned?
X	 ble	gwbdone 		;hmmm, phonky bounds report from DOS?
X	lea	rpstr(a5),a2            ;a2 = rpstr
X	cmpi.b	#';',4(a2)              ;Matches a typical report template?
X	 bne	gwbdone 		;nope, got some weird junk back?
X	cmpi.b	#'r',-1(a2,d4.w)        ;Last byte is 'r' for report?
X	 bne	gwbdone 		;Nope, message fubar!
X
X* Parse the height and width variables from the field now
X* Our report format looks like this in hex:
X*	9b 31 3b 31 3b y2 y1 3b x2 x1 20 72
X* Or in ascii:
X*	<0x9b>1;1;20;77 r
X* Which would indicate a width of 77 cols and a height of 20 rows for
X* the current console device
X*
X* REGS: a2 points to beginning of 'r' terminated string
X
X	addq.w	#5,a2			;Point to first char of Y size
X	moveq	#0,d1			;Clear out work reg
X
X* Convert ascii rows value to LONG, update host data
X	move.b	(a2)+,d1                ;Grab a Y
X	subi.w	#'0',d1                 ;Less ascii offset
X	cmpi.b	#';',(a2)               ;Any more Y digits?
X	 beq.s	1$			;Nope
X	mulu	#10,d1			;Else shift by 10
X	add.b	(a2)+,d1                ;Add least significant Y digit
X	subi.b	#'0',d1                 ;Less ascii offset
X	cmpi.b	#';',(a2)               ;Any more Y digits?
X	 beq.s	1$			;Nope
X	mulu	#$000a,d1		;Else shift by 10
X	add.b	(a2)+,d1                ;Add least significant Y digit
X	subi.b	#'0',d1                 ;Less ascii offset
X					;We'll assume screen height < 999 rows
X1$
X* Convert ascii columns value to LONG, update host data
X	addq.w	#1,a2			;Move past the ';' separator
X	moveq	#0,d2			;Zap work reg
X	move.b	(a2)+,d2                ;Grab msd of X
X	cmpi.b	#' ',d2                 ;Premature end?
X	 beq	gwbdone 		;Huh, must be garbage - don't update VPARMS
X	cmpi.b	#';',d2                 ;Also a possible error
X	 beq	gwbdone
X	cmpi.b	#'r',d2                 ;And what about this?
X	 beq	gwbdone
X
X	subi.b	#'0',d2                 ;Okay, adjust ascii offset
X	cmpi.b	#' ',(a2)               ;Hit end of report?
X	 beq.s	2$			;Yep
X	mulu	#$000a,d2		;Else shift by 10
X	add.b	(a2)+,d2                ;Add next digit
X	subi.b	#'0',d2                 ;Ascii adjust
X	cmpi.b	#' ',(a2)               ;Hit end of report?
X	 beq.s	2$			;Yep
X	mulu	#$000a,d2		;Else shift by 10
X	add.b	(a2),d2                 ;Add next digit
X	subi.b	#'0',d2                 ;Ascii adjust
X
X2$
Xgwbupdate:
X* Finally, update parameters by reference
X	movea.l height(a5),a0           ;Grab height VPARM
X	move.l	d1,(a0)                 ;*height = d1
X	movea.l width(a5),a0            ;Grab width VPARM
X	move.l	d2,(a0)                 ;*width = d2
X
Xgwbdone:
X	movem.l (sp)+,d2-d4/a2/a6
X	unlk	a5
X	rts
X
X* --------------------------------------------------------------------- *
X* void __asm SetConsoleType(flag, id, packet, port)
X*   register __d0 long flag;
X*   register __a0 struct Process *id;
X*   register __a1 struct StandardPacket *packet;
X*   register __a2 struct MsgPort *port;
X*
X* Flag = 1L -- Raw mode
X*      = 0L -- Cooked mode
X* --------------------------------------------------------------------- *
X	XDEF	SetConsoleType
XSetConsoleType:
X	movem.l a2/a3/a5/a6,-(sp)
X
X	movea.l a0,a3			;Copy process pointer
X	movea.l a1,a5			;Copy packet pointer
X	lea	sp_Pkt(a5),a0           ;a0 = &packet->sp_Pkt
X	move.l	a0,sp_Msg+LN_NAME(a5)   ;p->sp_Msg.mn_Node.ln_Name = &p->sp_Pkt
X	lea	sp_Msg(a5),a0           ;a0 = &packet->sp_Msg
X	move.l	a0,sp_Pkt+dp_Link(a5)   ;p->sp_Pkt.dp_Link = &p->sp_Msg
X	move.l	a2,sp_Pkt+dp_Port(a5)   ;p->sp_Pkt.dp_Port = replyport
X	move.l	#ACTION_SCREEN_MODE,sp_Pkt+dp_Type(a5)  ;Set function
X
X	tst.w	d0			;On or Off?
X	 beq	1$
X	move.l	#-1,sp_Pkt+dp_Arg1(a5)  ;RAW ON
X	bra.s	2$
X1$
X	clr.l	sp_Pkt+dp_Arg1(a5)      ;RAW OFF
X2$
X	movea.l a3,a0
X	movea.l a5,a1
X	SYS	PutMsg,4		;PutMsg(proc, packet)
X
X	movea.l a2,a0
X	SYS	WaitPort		;WaitPort(port)
X	movea.l a2,a0
X	SYS	GetMsg			;(void)GetMsg(port)
X
X	movem.l (sp)+,a2/a3/a5/a6
X	rts
X
X* ------------------------------------------------------------------------- *
X* struct MsgPort *CreatePort(name, pri) (a0/d0)
X* ------------------------------------------------------------------------- *
X	XDEF	CreatePort
XCreatePort:
X	movem.l d5/d7/a2/a5/a6,-(sp)
X
X	move.l	a0,a5			;Save Name
X	move.l	d0,d5			;Save Pri
X
X* Allocate a free signal, crap out if we can't
X	moveq	#-1,d0
X	SYS	AllocSignal,4
X	cmp.l	#-1,d0			;Did we get a signal?
X	 bne.s	cpgotsig		;Yep
X	moveq	#0,d0			;Otherwise return NULL
X	bra	cpdone
X
Xcpgotsig:
X	move.l	d0,d7			;Save our signal
X
X* Allocate memory for MsgPort
X	moveq	#MP_SIZE,d0		;Size of MsgPort
X	jsr	@myalloc		;Allocate it
X	tst.l	d0			;Did we get it?
X	 bne.s	cpgotport		;Yep
X
X	move.l	d7,d0			;Otherwise crap out, free signal
X	SYS	FreeSignal
X	moveq	#0,d0			;Return NULL
X	bra	cpdone
X
Xcpgotport:
X	move.l	d0,a2			;This is our new port!
X	move.l	a5,LN_NAME(a2)          ;port->mp_Node.ln_Name = name
X	move.b	d5,LN_PRI(a2)           ;port->mp_Node.ln_Pri = priority
X	move.b	#NT_MSGPORT,LN_TYPE(a2) ;port->mp_Node.ln_Type = NT_MSGPORT
X	move.b	#PA_SIGNAL,MP_FLAGS(a2) ;port->mp_Flags = PA_SIGNAL
X	move.b	d7,MP_SIGBIT(a2)        ;port->mp_SIGBIT = sigBit
X	suba.l	a1,a1
X	SYS	FindTask
X	move.l	d0,MP_SIGTASK(a2)       ;port->mp_SIGTASK = FindTask(0L)
X
X	cmpa.l	#0,a5			;Is this a new name?
X	beq.s	cpnoname		;Nope, add it to the msg list
X
X	movea.l a2,a1
X	SYS	AddPort 		;Otherwise add this port
X	move.l	a2,d0			;Return port pointer
X	bra.s	cpdone
X
Xcpnoname:
X* Initialized New List head
X	lea	MP_MSGLIST(a2),a0       ;a0 = &port->mp_MsgList
X	move.l	a0,(a0)                 ;list->lh_Head = list
X	addq.l	#4,(a0)                 ;list->lh_Head += 4L
X	clr.l	4(a0)                   ;list->lh_Tail = 0L
X	move.l	a0,8(a0)                ;list->lh_TailPred = list
X	move.l	a2,d0			;Return port pointer
X
Xcpdone:
X	movem.l (sp)+,d5/d7/a2/a5/a6
X	rts
X
X* ------------------------------------------------------------------------- *
X* DeletePort(port)(d0)
X* ------------------------------------------------------------------------- *
X	XDEF	DeletePort
XDeletePort:
X	movem.l a5/a6,-(sp)
X
X	move.l	d0,a5
X	movea.l $4,a6
X	tst.l	LN_NAME(a5)             ;Is there a name?
X	beq.s	dpnoname
X
X	move.l	d0,a1
X	SYS	RemPort 		;RemPort(port)
X
Xdpnoname:
X	move.b	#$ff,LN_TYPE(a5)        ;port->mp_Node.ln_Type = 0xff
X	move.l	#-1,MP_MSGLIST(a5)      ;port->mp_MsgList.lh_Head = -1L
X
X	moveq	#0,d0
X	move.b	MP_SIGBIT(a5),d0        ;d0 = port->mp_SigBit
X	SYS	FreeSignal		;FreeSignal(d0)
X
X	movea.l a5,a0
X	jsr	@myfree 		;FreeBlock(port)
X
X	movem.l (sp)+,a5/a6
X	rts
X
X* ------------------------------------------------------------------------
X* FibFileDate(fib_date, datestr, timestr)
X*		a0	  a1	   8(a5)
X*   struct DateStamp *fib_date;
X*   char *datestr, *timestr;
X*   Calculate date based on DateStamp structure and return a pointer
X* to the formatted date string.
X* ------------------------------------------------------------------------
X	XDEF	@FibFileDate
X@FibFileDate:
X	link	a5,#0
X	movem.l d3-d7/a2-a3/a6,-(sp)
X
X	movea.l a1,a3			;a3 = datestr, 8(a5) = timestr
X	movea.l a0,a1			;Grab datestamp pointer
X	moveq	#78,d7			;Initial year = 1978
X
X	move.l	(a1),d5                 ;days = fib_date->ds_Days
X	 blt	ffdbaddate		;Hey! you can't be negative! Invalid date...
X
X* Determine what year it is
X	divu	#1461,d5
X	move.l	d5,d0			;Stash it
X	ext.l	d5
X	lsl.l	#2,d5
X	add.l	d5,d7			;year += (days / 1461) * 4
X
X* Count how many months into that year
Xffdgetmo:
X	swap	d0			;days %= 1461
X	move.w	d0,d5
X
X1$	tst.w	d5			;Out of days yet?
X	 beq.s	3$			;Yep, done here
X
X	move.w	#365,d6 		;Else month_days = 365
X	move.w	d7,d0			;Grab year
X	andi.w	#3,d0			;if (year & 3) == 0 Leap year?
X	 bne.s	2$			;Nope
X	addq.w	#1,d6			;Otherwise bump month_days
X
X2$	cmp.w	d6,d5			;is day < month_days?
X	 blt.s	3$			;yep, done here
X	sub.w	d6,d5			;otherwise day -= month_days
X
X	addq.l	#1,d7			; year++
X	bra	1$
X3$
X
X* Count how many days into that month of that year
Xffdgetday:
X;for (i = 0, day++; i < 12; i++)
X	moveq	#0,d4			;current month = 0
X	moveq	#0,d6			;Zap hinybs
X	addq.w	#1,d5
X	lea	dayspermonth(a4),a0
X
X1$
X	move.b	0(a0,d4.w),d6           ;month_days = dayspermonth[i]
X
X	cmpi.w	#1,d4			;if (i == 1 && (year & 3) == 0)
X	 bne.s	2$
X	move.w	d7,d0
X	andi.w	#3,d0
X	 bne.s	2$
X	addq.w	#1,d6			;month_days++
X
X2$	cmp.w	d6,d5			;if (day <= month_days)
X	 ble.s	4$			;Break out, found the right month
X
X	sub.w	d6,d5			;Else, day -= month_days
X
X	addq.w	#1,d4			;i++
X3$	cmpi.w	#12,d4			;Done all months yet?
X	 blt	1$			;Nope
X
X4$
Xffdprint:
X1$	cmpi.l	#99,d7			;while (year >= 100)
X	 ble.s	2$
X	subi.l	#100,d7 		;year -= 100
X	bra	1$
X2$
X;asprintf(datestr, "%02d-%02d-%02d %02d:%02d:%02d", i + 1, day, year, hour, min, sec)
X	move.l	8(a1),d0                ;sec = fib_date->ds_Tick / 50;
X	divu	#50,d0
X	ext.l	d0
X	move.l	d0,-(sp)                ;Push secs
X	move.l	4(a1),d0                ;min = fib_date->ds_Minute
X	move.l	d0,d1			;Clone it
X	divu	#60,d0
X	moveq	#0,d3
X	move.w	d0,d3			;hour = min / 60
X	mulu	#60,d0
X	sub.w	d0,d1			;min -= hour * 60
X	move.l	d1,-(sp)                ;Push mins
X	move.l	d3,-(sp)                ;Push hours
X	pea	timepat(a4)             ;Push the format pattern
X	move.l	8(a5),-(sp)             ;Push destination buffer, datestr
X	jsr	asprintf
X	lea	20(sp),sp
X
X	move.l	d5,-(sp)                ;Push day
X	addq.w	#1,d4			;Push month (offset by 1!)
X	move.l	d4,-(sp)
X	move.l	d7,-(sp)                ;Push year
X	pea	datepat(a4)             ;Push the format pattern
X	move.l	a3,-(sp)                ;Push destination buffer
X	jsr	asprintf
X	lea	20(sp),sp
X
Xffddone:
X	movem.l (sp)+,d3-d7/a2-a3/a6
X	unlk	a5
X	rts
X
Xffdbaddate:
X	lea	badtimestr(a4),a1       ;stpcpy (timestr, "00:00:00");
X	movea.l 8(a5),a0
X	jsr	@stpcpy
X	lea	baddatestr(a4),a1       ;stpcpy (datestr, "00-00-00");
X	movea.l a3,a0
X	jsr	@stpcpy
X	bra	ffddone
X
X*----------------------------------------------------------------------
X* LONG iswild(name)
X*   char *name;
X*	   a0
X* Search a string for wild characters, return 1 if found
X*----------------------------------------------------------------------
X	XDEF	@iswild
X@iswild:
X	moveq	#0,d0			;Clear out our character register
Xischk1:
X	move.b	(a0)+,d0                ;Grab a char
X	 beq.s	iwdone			;Might be end of string?
X	cmpi.b	#'*',d0                 ;Is it *?
X	 beq.s	iswdone 		;yep, is wild
X	cmpi.b	#'?',d0                 ;Is it a qmark
X	 bne.s	ischk1			;Nope, check next character
X
Xiswdone:
X	moveq	#1,d0
Xiwdone:
X	rts
X
X* ------------------------------------------------------------------------
X; Compare a wild card name with a normal name
X; LONG wildmatch (name, wild)
X;   char *name, *wild;
X;	   a0	  a1
X* ------------------------------------------------------------------------
X	XDEF	@wildmatch
X@wildmatch:
X	link	a5,#-64
X	movem.l d2-d3/a2-a3,-(sp)
X
X	move.l	LSFlags(a4),d2          ;Grab flags
X	movea.l a0,a2			;Grab name
X	movea.l a1,a3			;Grab pattern
X	lea	-64(a5),a0              ;back[0][0]
X	lea	-60(a5),a1              ;back[0][1]
X
X	moveq	#0,d3			;bi = 0
X
Xwmloop1:
X	tst.b	(a2)                    ;End of name?
X	bne.s	wmnoteon
X	tst.b	(a3)                    ;End of pattern?
X	beq	wmmatched		;Yep, we matched
X
Xwmnoteon:
X	cmpi.b	#'*',(a3)               ;Is it a splat?
X	bne.s	wmnotstar		;Nope, maybe '?'
X
X	cmpi.w	#64,d3			;Have we hit max expression depth?
X	beq	wmnomatch		;Yep, ran out of room in recursion table
X
X;back[bi][0] = w
X	move.l	a3,0(a0,d3.w)           ;Stash pointer to this '*' in table
X
X;back[bi][1] = n
X	move.l	a2,0(a1,d3.w)
X
X	addq.w	#8,d3			;++bi
X	addq.w	#1,a3			;++w
X	bra.s	wmloop1 		;Check next
X
Xwmgoback:
X	subq.w	#8,d3			;--bi
X	move.l	a0,d0
Xwmback1:
X	tst.w	d3			;while (bi >= 0 && *back[bi][1] == '\x0')
X	blt.s	wmbacked
X	movea.l 0(a1,d3.l),a0
X	tst.b	(a0)
X	bne.s	wmbacked
X
X	subq.w	#8,d3			;--bi
X	bra.s	wmback1
X
Xwmbacked:
X	tst.w	d3			;if (bi < 0)
X	blt.s	wmnomatch		;return (0)
X
X	movea.l d0,a0
X	movea.l 0(a0,d3.w),a3           ;w = back[bi][0] + 1
X	addq.w	#1,a3
X
X	addq.l	#1,0(a1,d3.w)
X	movea.l 0(a1,d3.l),a2           ;n = ++back[bi][1]
X
X	addq.w	#8,d3			;++bi
X	bra.s	wmloop1
X
Xwmnotstar:
X	cmpi.b	#'?',(a3)               ;Is it '?'
X	bne.s	wmnotqmark
X
X	tst.b	(a2)                    ;Reached end of string?
X	bne.s	wmincpoint		;Nope, move on to next char
X
X	tst.w	d3			;Are we at top level of expression?
X	beq.s	wmnomatch		;Yep, expression didn't match
X	bra.s	wmgoback		;Otherwise pop a level and try to match
X
Xwmnotqmark:
X	move.b	(a2),d0                 ;Grab a char from bstr
X	move.b	(a3),d1                 ;Grab a char from astr
X	btst.l	#21,d2			;LSFlags & IGNORECASEWILD?
X	beq.s	2$			;Nope, blow off lowercasing crap
X
X	cmpi.b	#$40,d0 		;less than @ character?  (for bstr)
X	bls.s	1$			;Yep
X	cmpi.b	#$5a,d0 		;Greater than Z?
X	bhi.s	1$			;Yep
X	addi.b	#$20,d0
X1$
X	cmpi.b	#$40,d1 		;less than @ character?  (for astr)
X	bls.s	2$			;Yep
X	cmpi.b	#$5a,d1 		;Greater than Z?
X	bhi.s	2$			;Yep
X	addi.b	#$20,d1
X2$
X	cmp.b	d0,d1			;*n = *w?
X	beq.s	wmincpoint		;Yep, move on past
X
X	tst.w	d3			;Are we at top expression level?
X	beq.s	wmnomatch		;Yep, they didn't match
X	bra.s	wmgoback		;Nope, process next part
X
Xwmincpoint:
X	tst.b	(a2)                    ;Done with name?
X	beq.s	wmnamend		;Yep
X	addq.w	#1,a2			;Otherwise increment name pointer
X
Xwmnamend:
X	tst.b	(a3)                    ;End of pattern?
X	beq.s	wmmatched		;Yep, we matched
X	addq.w	#1,a3			;Otherwise inc wild pointer, match next char
X	bra	wmloop1
X
Xwmmatched:
X	moveq	#1,d0
X	bra.s	wmdone
X
Xwmnomatch:
X	moveq	#0,d0
X
Xwmdone:
X	movem.l (sp)+,d2-d3/a2-a3
X	unlk	a5
X	rts
X
X* --------------------------------------------------------------------- *
X* BOOL CompFibs (keytype, a,   b)
X*		    d0	 a0   a1
X*   LONG keytype;
X*   struct FileInfoBlock *a, *b;
X*
X* Used by SortFibs to determine precedence of Fibs.
X* keytype is one of 0, 1, 2, or 3:
X*   0=alpha, 1=size, 2=date, 3=diskkey
X* --------------------------------------------------------------------- *
X	XDEF	@CompFibs
X@CompFibs:
X	movem.l d2-d3/a2,-(sp)
X
X	move.l	d0,d2			;Stash keytype
X
X* Prioritize Dirs/Files?
X	move.l	LSFlags(a4),d3          ;Grab flags
X
X	btst.l	#17,d3			;LSFlags & SEPFILESDIRS?
X	beq.s	cftstsort		;No, don't bother comparing EntryTypes
X
X	move.l	fib_DirEntryType(a0),d0
X	cmp.l	fib_DirEntryType(a1),d0
X	blt.s	1$			;a0 is < a1, (dir < file)
X	beq.s	cftstsort		;a0 is == a1, try next test
X
X	moveq	#0,d0			;a0 is > a1, (file > dir)
X	bra.s	2$
X1$
X	moveq	#1,d0			;greater than, (dir < file)
X
X2$	btst.l	#16,d3			;LSFlags & FILESFIRST?
X	beq	cfexit0 		;Nope, default Dirs first
X	bchg.l	#0,d0			;Else d0 ^= 1, reverse sense
X	bra	cfexit0
X
X* Both entries are the same type, now see about sorting them
Xcftstsort:
X	btst.l	#6,d3			;LSFlags & NOSORTFLAG set?
X	bne	cffalse 		;Yep, always AddTail to list
X
X* Switch keytype
X	tst.w	d2			;Alphabetize?
X	bne.s	cfnalpha		;Nope
X
X* Compare lexigraphically, optionally ignoring case differences
Xcfalpha:
X	lea	fib_FileName(a0),a0     ;a = &Fipb->fib_FileName
X	lea	fib_FileName(a1),a1     ;b = &Fipb->fib_FileName
X
X; for(; *a && tolower(*a) == tolower(*b); a++, b++); [tolower() crap optional]
Xlccstart:
X	tst.b	(a0)                    ;Is there a char here at source?
X	beq.s	lcceostr		;Nope, fell off the end
X
X	move.b	(a1)+,d1                ;Grab a char from bstr
X	move.b	(a0)+,d0                ;Grab a char from astr
X	btst.l	#20,d3			;LSFlags & IGNORECASELIST?
X	beq.s	2$			;Nope, blow off lowercasing crap
X
X	cmpi.b	#$40,d1 		;less than @ character?  (for bstr)
X	bls.s	1$			;Yep
X	cmpi.b	#$5a,d1 		;Greater than Z?
X	bhi.s	1$			;Yep
X	addi.b	#$20,d1
X1$
X	cmpi.b	#$40,d0 		;less than @ character?  (for astr)
X	bls.s	2$			;Yep
X	cmpi.b	#$5a,d0 		;Greater than Z?
X	bhi.s	2$			;Yep
X	addi.b	#$20,d0
X2$
X	cmp.b	d0,d1			;are they the same?
X	beq.s	lccstart		;Yep, compare next pair of chars
X
Xlcceostr:
X	sub.b	d1,d0			;return([tolower](*astr) - [tolower](*bstr))
X	bgt.s	cftrue			; > 0?, return TRUE
X	bra.s	cffalse 		;Else return FALSE
X
Xcfnalpha:
X	subq.w	#1,d2			;Size?
X	bne.s	cfnsize 		;Nope
X
X* Compare fib_Sizes
X	move.l	fib_Size(a0),d0         ;d0 = afib->fib_Size
X	cmp.l	fib_Size(a1),d0         ;b->fib_Size < a->fib_Size?
X	blt.s	cftrue			;Yep, return TRUE
X	bgt.s	cffalse 		;>, return FALSE
X	bra.s	cfalpha 		;Else it's a tie, alphabetize
X
Xcfnsize:
X	subq.w	#1,d2			;Date?
X	bne.s	cfndate 		;No
X
X* Compare fib_DateStamps
X	lea	fib_DateStamp(a0),a0    ;a = &afib->fib_DateStamp
X	lea	fib_DateStamp(a1),a1    ;b = &bfib->fib_DateStamp
X	jsr	@CompareDateStamps
X	tst.l	d0
X	blt.s	cftrue
X	bgt.s	cffalse
X	bra.s	cfalpha 		;same date; alphabetize
X
Xcfndate:
X*Compare fib_DiskKeys
X	move.l	fib_DiskKey(a0),d0      ;d0 = afib->fib_DiskKey
X	cmp.l	fib_DiskKey(a1),d0      ;b->fib_DiskKey < a->fib_DiskKey?
X	beq.s	cfalpha 		;shouldn't happen [bad filesys if so]
X	blt.s	cffalse 		;<, return FALSE
X
Xcftrue:
X	moveq	#1,d0
X	bra.s	cfexit
Xcffalse:
X	moveq	#0,d0
Xcfexit:
X	btst.l	#9,d3			;LSFlags & REVFLAG?
X	beq.s	1$			;Nope
X	bchg.l	#0,d0			;Else invert boolean result
X1$
Xcfexit0:
X	movem.l (sp)+,d2-d3/a2
X	rts
X
X* --------------------------------------------------------------------- *
X* LONG CompareDateStamps(adate, bdate)
X*  d0			  a0	  a1
X*   struct DateStamp *adate, *bdate;
X* --------------------------------------------------------------------- *
X	XDEF	@CompareDateStamps
X@CompareDateStamps:
X	move.l	ds_Days(a0),d0          ;d0 = adate->ds_Days
X	sub.l	ds_Days(a1),d0          ;b->ds_Days > a->ds_Days?
X	bne.s	1$			;Return b->day - a->day
X
X;They are the same day, check min/tick
X	move.l	ds_Minute(a0),d0
X	sub.l	ds_Minute(a1),d0        ;d0 = amin - bmin
X	muls	#3000,d0		;     * 3000
X	add.l	ds_Tick(a0),d0
X	sub.l	ds_Tick(a1),d0          ;     + atick - btick
X1$
X	rts
X
X* --------------------------------------------------------------------- *
X* VOID InsertFibNode(hfib, newfib)
X*		      a0     a1
X*   struct List *hfib;
X*   struct FibEntry *newfib;
X*
X* Compare data in newfib->Fib with nodes in the list until we
X* find the insertion point.
X* --------------------------------------------------------------------- *
X	XDEF	@InsertFibNode
X@InsertFibNode:
X	movem.l d2/a2-a3/a5/a6,-(sp)
X
X	move.l	sortkey(a4),d2
X	movea.l a0,a3			;a3 = hfib
X	movea.l a1,a2			;a2 = newfib
X
X	movea.l LH_HEAD(a3),a5          ;afib = hfib->lh_Head
X
X1$	tst.l	fe_Node+LN_SUCC(a5)     ;afib->fe_Node.mln_Succ != 0?
X	beq.s	4$
X
X	movea.l fe_Fib(a2),a1
X	movea.l fe_Fib(a5),a0
X	move.l	d2,d0
X	jsr	@CompFibs		;CompFibs(sortkey, afib->Fib, newfib->Fib)
X	tst.w	d0
X	bne.s	4$
X	movea.l fe_Node+LN_SUCC(a5),a5  ;afib = afib->fe_Node.mln_Succ
X	bra	1$
X
X4$	movea.l a3,a0			;a0 = List *
X	movea.l a2,a1			;a1 = Node *
X	movea.l fe_Node+LN_PRED(a5),a2  ;a2 = Pred *
X	SYS	Insert,4		;Insert(hfib, newfib, afib->fe_Node.mln_Succ)
X
X	movem.l (sp)+,d2/a2-a3/a5/a6
X	rts
X
X* --------------------------------------------------------------------- *
X* LONG FillFibEntry (headfib, fibp)
X*		       a0      a1
X*   struct List *headfib;
X*   struct FileInfoBlock *fibp;
X* --------------------------------------------------------------------- *
X	XDEF	@FillFibEntry
X@FillFibEntry:
X	movem.l a2-a3/a5/a6,-(sp)
X	movea.l a0,a2			;a2 = head of list
X	movea.l a1,a3			;a3 = fileinfoblock
X
X	jsr	@AllocFib		;Allocate a new fib
X	tst.l	d0			;Got it?
X	beq.s	3$			;Nope, return 0
X	movea.l d0,a5			;a5 = tfibp = AllocFib()
X
X	move.l	#fib_SIZEOF,d0
X	movea.l fe_Fib(a5),a1
X	movea.l a3,a0
X	SYS	CopyMem,4		;CopyMem(fibp, tfibp->Fib, sizeof(struct fib))
X
X	movea.l a5,a1
X	movea.l a2,a0
X
X	jsr	@InsertFibNode		;InsertFibNode(headfib, tfibp)
X
X	moveq	#1,d0			;return(1)
X3$
X	movem.l (sp)+,a2-a3/a5/a6
X	rts
X
X* --------------------------------------------------------------------- *
X	XDEF	@nullstub
X@nullstub:
X	moveq	#0,d0
X	rts
X
X* --------------------------------------------------------------------- *
X* LONG GetPathString (dest, src)
X*  d0		       a0    a1
X*   BYTE *dest, *src;
X* --------------------------------------------------------------------- *
X	XDEF	@GetPathString
X@GetPathString:
X	move.l	a2,-(sp)
X
X	moveq	#0,d0			;Zero return dest length
X
X* Find end of src string
X	movea.l a1,a2			;Save src start address
X1$	tst.b	(a1)+                   ;while (*src++ != 0)
X	bne.s	1$
X
X* Work backwards till we find a ':' or a '/'
X2$	move.b	-(a1),d1                ;c = *(--src)
X	cmpi.b	#':',d1                 ;Hit a colon?
X	beq.s	4$			;Yep, found our path end
X	cmpi.b	#'/',d1                 ;Hit a slash?
X	bne.s	3$			;Nope, try next char
X	cmpa.l	a2,a1			;At first char?
X	beq.s	4$			;Yep, leave the single slash
X	cmpi.b	#'/',-1(a1)             ;Next char back is also a '/'?
X	beq.s	4$			;Yep, allow multiple slashes
X	subq.w	#1,a1			;Else backup to previous char, eliminate '/'
X	bra.s	4$
X3$
X	cmpa.l	a2,a1			;Back at start of src?
X	bhi.s	2$			;Nope, try previous src char
X	bra.s	gpsdone 		;Else no dest, return
X4$
X* Copy path portion to dest
Xgpscpy:
X	cmpa.l	a2,a1			;Past end address?
X	bcs.s	gpsdone 		;Yep, terminate
X	move.b	(a2)+,(a0)+             ;Copy a char from src to dest
X	addq.w	#1,d0			;Bump dest length count
X	bra.s	gpscpy			;Check end address
Xgpsdone:
X	clr.b	(a0)                    ;Null terminate dest
X
X	movea.l (sp)+,a2
X	rts
X
X* --------------------------------------------------------------------- *
X* LONG GetFileString (dest, src)
X*  d0		       a0    a1
X*   BYTE *dest, *src;
X* --------------------------------------------------------------------- *
X	XDEF	@GetFileString
X@GetFileString:
X	move.l	a2,-(sp)
X
X	moveq	#0,d0			;Zero return dest length
X
X* Find end of src string
X	movea.l a1,a2			;Save src start address
X1$	tst.b	(a1)+                   ;while (*src++ != 0)
X	bne.s	1$
X
X* Work backwards till we find a ':' or a '/'
X2$	move.b	-(a1),d1                ;c = *(--src)
X	cmpi.b	#':',d1                 ;Hit a colon?
X	beq.s	4$			;Yep, found our path end
X	cmpi.b	#'/',d1                 ;Hit a slash?
X	beq.s	4$			;Nope, try next char
X3$
X	cmpa.l	a2,a1			;Back at start of src?
X	bhi.s	2$			;Nope, try previous src char
X	bra.s	gfscpy			;Else no path, entire src is filename
X4$
X	addq.w	#1,a1			;Move past ':' or '/'
X
X* Copy name portion to dest
Xgfscpy:
X	move.b	(a1)+,(a0)+             ;Copy a char from src to dest
X	beq.s	2$
X	addq.w	#1,d0			;Bump dest length count
X	bra.s	gfscpy			;Check end address
X2$
X	movea.l (sp)+,a2
X	rts
X
X* ------------------------------------------------------------------------- *
X* BYTE *astrncpy(dst, src, len)
X* d0/a0 	 a0   a1    d0
X* Takes text in a1, copies d0 bytes to text in a0.
X* a0 returns pointing to null at end of final text.
X* Dest text is always null terminated.
X* ------------------------------------------------------------------------- *
X	XDEF	@astrncpy
X@astrncpy:
X1$	subq.l	#1,d0			;Dec count
X	blt.s	2$			;Done!
X
X	move.b	(a1)+,(a0)+             ;Copy a byte
X	bne.s	1$			;Do until end of src or cnt < 0
X2$
X	clr.b	(a0)                    ;Null terminate dest
X	move.l	a0,d0			;Return in d0 also
X	rts
X
X* ------------------------------------------------------------------------- *
X* VOID amovmem(src, dst, len)
X*	       a0    a1   d0
X* Takes text in a0, copies d0 bytes to text in a1. Correctly handles
X* overlapping memory.
X* ------------------------------------------------------------------------- *
X	XDEF	amovmem
Xamovmem:
X	cmpa.l	a0,a1			;Low to high or high to low?
X	 bcs.s	2$			;High to low, copy forward
X	adda.w	d0,a0			;Else start at end, copy backward
X	adda.w	d0,a1
X
X1$	move.b	-(a0),-(a1)
X	subq.w	#1,d0
X	 bgt	1$
X	bra.s	amdone
X
X2$	move.b	(a0)+,(a1)+
X	subq.w	#1,d0
X	 bgt	2$
Xamdone:
X	rts
X
X* --------------------------------------------------------------------- *
X* BYTE *aindex(BYTE *, BYTE);
X*  d0		a0	d0
X* --------------------------------------------------------------------- *
X	XDEF	@aindex
X@aindex:
X1$	cmp.b	(a0),d0
X	 beq.s	aifound
X	tst.b	(a0)+
X	 beq.s	ainomatch
X	bra	1$
X
Xainomatch:
X	moveq	#0,d0
X	rts
X
Xaifound:
X	move.l	a0,d0
X	rts
X
X* --------------------------------------------------------------------- *
X* LONG MakePathString(lock, dest)
X*		       a0     a1
X*   struct FileLock *lock;
X*   BYTE *dest;
X*
X* DESCRIPTION:
X*   Given text and a filelock, construct entire pathname and
X* return in dest.
X* --------------------------------------------------------------------- *
X	XDEF	@MakePathString
X@MakePathString:
X	movem.l d2-d5/d7/a2-a3/a6,-(sp)
X
X* Grab pointer to lock and dest text to fill
X	move.l	a0,d3			;d3 = lock
X	movea.l a1,a2			;a2 = dest
X	clr.b	(a2)                    ;NULL terminate dest
X	moveq	#0,d5			;LockFlag = 0
X
X* Allocate a FileInfoBlock for local use
X	move.l	#fib_SIZEOF,d0
X	jsr	@myalloc
X	move.l	d0,d7			;d7 = *fib
X	 beq	mpsfailed		;Whoops no mem? return!
X
X	movea.l DOSBase(a4),a6          ;DOSBase calls from here on
X
X* while (lock != 0)
X1$
X	tst.l	d3			;Got a lock?
X	 beq.s	mpsokay 		;Nope, must be at root
X
X* Examine the current lock
X	move.l	d3,d1
X	move.l	d7,d2
X	SYS	Examine 		;Examine(lock, fib)
X	tst.l	d0			;Okay?
X	 beq.s	mpsfailed		;Nope, some sort of dos failure?
X
X	movea.l d7,a1
X	cmpi.b	#' ',fib_FileName(a1)   ;if (fib->fib_FileName[0] >= ' ')
X	 bcs.s	3$			;Nope, don't bother inserting?
X
X	tst.b	(a2)                    ;if (dest[0] != 0)
X	 beq.s	2$
X	lea	SlashStr(a4),a1
X	movea.l a2,a0
X	jsr	@InsertPathString	;InsertPathString(dest, "/");
X2$
X	movea.l d7,a1
X	lea	fib_FileName(a1),a1
X	movea.l a2,a0
X	jsr	@InsertPathString	;InsertPathString(dest, fib->fib_FileName)
X3$
X* Okay, move up one directory
X	move.l	d3,d4			;oldlock = lock
X
X	move.l	d3,d1
X	SYS	ParentDir
X	move.l	d0,d3			;lock = ParentDir(lock)
X
X	tst.w	d5			;LockFlag set?
X	 bne.s	4$			;Yep, unlock
X	moveq	#1,d5			;Else LockFlag = 1, unlock next time
X	 bra	1$			;Next directory up
X4$
X	move.l	d4,d1
X	SYS	UnLock			;UnLock(oldlock)
X	bra	1$			;Examine
X
Xmpsokay:
X* See if root was RAM:, special case
X	movea.l d7,a1			;a1 = fib
X	cmpi.b	#' ',fib_FileName(a1)   ;if (fib->fib_FileName[0] >= ' ')
X	 bcc.s	1$			;Yep, not 1.1/1.2 RAM:
X	lea	RamNameStr(a4),a1       ;Else...
X	movea.l a2,a0
X	jsr	@InsertPathString	;InsertPathString(dest, "RAM:")
X	bra.s	mpsdone
X1$
X* Find last slash we tacked on, change to a colon, or, add a colon
X	moveq	#'/',d0
X	movea.l a2,a0
X	jsr	@aindex 		;d0 = strchr(dest, '/')
X	tst.l	d0			;Do we have a slash?
X	 beq.s	2$			;Nope, at root....
X	movea.l d0,a0
X	move.b	#':',(a0)               ;Else change first '/' to a ':'
X	bra.s	mpsdone
X
X* No slash, must be locked at the root.  Append a colon to the dest.
X2$
X	lea	ColonStr(a4),a1
X	movea.l a2,a0
X	jsr	@strcat 		;strcat (dest, ":")
X	bra.s	mpsdone
X
X* Come here if an error occured, return empty text to caller
Xmpsfailed:
X	clr.b	(a2)                    ;dest[0] = (BYTE)0
X	moveq	#0,d3			;return (0L)
X	bra.s	mpsdeall
X
X* Come here if everything is okay, deallocate FileInfoBlock
Xmpsdone:
X	moveq	#1,d3			;return (1L)
X
Xmpsdeall:
X	tst.l	d7			;Did we allocate a fib?
X	 beq.s	mpsfinis		;nope
X	movea.l d7,a0			;Else free the memory
X	jsr	@myfree
X
Xmpsfinis:
X	move.l	d3,d0			;Put return value in d0
X	movem.l (sp)+,d2-d5/d7/a2-a3/a6
X	rts
X
X* --------------------------------------------------------------------- *
X* VOID InsertPathString(dest, source)
X*			 a0	a1
X*   BYTE *dest, *source;
X*
X* DESCRIPTION:
X*   Insert source text into dest text.
X* Special case for source length == 0, source must be RAM.
X* --------------------------------------------------------------------- *
X	XDEF	@InsertPathString
X@InsertPathString:
X	movem.l d7/a2-a3,-(sp)
X
X	movea.l a1,a3			;a3 = source
X	move.l	a0,a2			;a2 = dest
X
X	movea.l a3,a0
X	jsr	@strlen
X	move.l	d0,d7			;d7 = strlen(source)
X
X1$	movea.l a2,a0
X	jsr	@strlen 		;d0 = strlen(dest)
X
X	addq.w	#1,d0			;Bump the length to include zero byte at end
X	movea.l a2,a1
X	adda.w	d7,a1			;Push dest + slen
X	movea.l a2,a0			;Push dest
X	jsr	amovmem 		;amovmem(dest, dest + slen, strlen(dest) + 1)
X
X	move.w	d7,d0
X	movea.l a2,a1
X	movea.l a3,a0
X	jsr	amovmem 		;amovmem(source, dest, slen)
X
X	movem.l (sp)+,d7/a2-a3
X	rts
X
X* --------------------------------------------------------------------- *
X	END
X* --------------------------------------------------------------------- *
END_OF_FILE
if test 34948 -ne `wc -c <'src/lssup.a'`; then
    echo shar: \"'src/lssup.a'\" unpacked with wrong size!
fi
# end of 'src/lssup.a'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.