home *** CD-ROM | disk | FTP | other *** search
- * --------------------------------------------------------------------- *
- * LSSUP.A - Assembly support routines for ls.c *
- * Copyright © 1988 by Justin V. McCormick. All Rights Reserved. *
- * --------------------------------------------------------------------- *
- IDNT "lssup.a"
-
- include "asm:inc/macros.i"
-
- ; Assembler options for CAPE
- BASEREG B
- SMALLOBJ
- ; OPTIMON
- ; ADDSYM
- ; DEBUG
-
- ; Equates
- fib_FileName equ $8
- fib_Size equ $7C
- fib_NumBlocks equ $80
- fib_DateStamp equ $84
-
- ds_Days equ $0
- ds_Minute equ $4
- ds_Tick equ $8
-
- _LVOAddPort equ $FFFFFE9E
- _LVOAllocMem equ $FFFFFF3A
- _LVOAllocSignal equ $FFFFFEB6
- _LVODebug equ $FFFFFF8E
- _LVOFindTask equ $FFFFFEDA
- _LVOFreeMem equ $FFFFFF2E
- _LVOFreeSignal equ $FFFFFEB0
- _LVOGetMsg equ $FFFFFE8C
- _LVOPutMsg equ $FFFFFE92
- _LVORawDoFmt equ $FFFFFDF6
- _LVORemPort equ $FFFFFE98
- _LVORead equ $FFFFFFD6
- _LVOWaitPort equ $FFFFFE80
- _LVOWrite equ $FFFFFFD0
-
- pr_ConsoleTask EQU $A4
- MEMF_CLEAR EQU $10000
- MEMF_PUBLIC EQU $1
- sp_Msg EQU $0
- sp_Pkt EQU $14
- sp_SIZEOF EQU $44
- dp_Link EQU $0
- dp_Port EQU $4
- dp_Arg1 EQU $14
- dp_Type EQU $8
- ACTION_SCREEN_MODE EQU $3E2
- LN_NAME EQU $A
- LN_PRI EQU $9
- LN_TYPE EQU $8
- MP_FLAGS EQU $E
- MP_MSGLIST EQU $14
- MP_SIGBIT EQU $F
- MP_SIGTASK EQU $10
- MP_SIZE EQU $22
- NT_MSGPORT EQU $4
- PA_SIGNAL EQU $0
-
- * External constants
- XREF _DOSBase
- XREF _Out
- XREF _In
- * --------------------------------------------------------------------- *
- SECTION lssup,CODE
-
- * ------------------------------------------------------------------------- *
- * void asprintf(wstr, formatstring, args)
- * char *wstr;
- * char *formatstring;
- * char **args;
- *
- * Synopsis: Given formatstring and args to format, formats output to wstr.
- * Similar to sprintf(), except doesn't handle floats.
- * ------------------------------------------------------------------------- *
- XDEF _asprintf
- _asprintf:
- link a5,#0
- movem.l d0-d2/a0-a3,-(sp) ;Save everything we might clobber
-
- * Call format function to convert fmtstring and args to buffer on the stack
- movea.l 12(a5),a0 ;Grab format string
- lea 16(a5),a1 ;Grab EA of arguments
- lea kput1,a2 ;Grab EA of output subroutine
- movea.l 8(a5),a3 ;Grab EA of dest workspace
- SYS RawDoFmt,4 ;Format it into workspace
-
- movem.l (sp)+,d0-d2/a0-a3 ;Restore registers
- unlk a5 ;And stack frame
- rts
-
- * ------------------------------------------------------------------------- *
- * RawDoFmt() output routine for xprintf, called for each formatted char.
- * Takes byte in d0 and puts in buffer pointed to by a3, then increments a3.
- * ------------------------------------------------------------------------- *
- XDEF kput1
- kput1:
- move.b d0,(a3)+
- rts
-
- * --------------------------------------------------------------------- *
- * void GetWinBounds(width, height)
- * long *width, *height;
- *
- * Find current console window, determine width and height
- * in terms of current font, update width and height VPARMS passed.
- * --------------------------------------------------------------------- *
- rpstr equ -32
- rpport equ -12
- packet equ -8
- conid equ -4
-
- width equ 8
- height equ 12
-
- XDEF _GetWinBounds
- _GetWinBounds:
- link a5,#-32
- movem.l d2-d4/a2,-(sp)
-
- suba.l a1,a1
- SYS FindTask,4 ;d0 = FindTask(0L), our process
- movea.l d0,a0 ;Transfer to address reg
- move.l pr_ConsoleTask(a0),conid(a5) ;Save proc->pr_ConsoleTask
-
- moveq #0,d4 ;Clear our success status register
-
- moveq #0,d0
- movea.l d0,a0
- bsr.w CreatePort
- move.l d0,rpport(a5) ;rpport = CreatePort(0L, 0L)
- beq.w gwbdone ;Oops, no signals or ram available!
- move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
- moveq #sp_SIZEOF,d0
- SYS AllocMem
- move.l d0,packet(a5) ;packet = AllocMem(sizeof(*packet),MEMF_PUBLIC|MEMF_CLEAR)
- beq.w gwbfreeport ;Oops, no ram, free up port
-
- * Okay, we got our process id, reply port, and packet
- * Now toggle the console into raw mode
- movea.l rpport(a5),a2
- movea.l d0,a1
- movea.l conid(a5),a0
- moveq #1,d0
- bsr.w SetConsoleType ;SetConsoleType(1L, conid, packet, rpport)
-
- * Request a window bounds report
- moveq #4,d3
- lea gwbrstr(a4),a0
- move.l a0,d2
- move.l _Out(a4),d1
- SYS Write,_DOSBase(a4) ;Write(Output(), "\2330 q", 4L);
- cmpi.l #$0004,d0 ;Did the console choke on it?
- bne.w gwbsetcook ;hmmm, see if we can back out gracefully
-
- * Read the report string into stack buffer
- moveq #16,d3 ;Don't let it get longer than 16 characters
- lea rpstr(a5),a0 ;Point to input string area
- move.l a0,d2
- move.l _In(a4),d1
- SYS Read ;Read(Input(), rpstr, 16L)
- move.l d0,d4 ;Save read length while we close shop
-
- * Turn the console back to cooked mode pronto to avoid cursor blink
- gwbsetcook:
- movea.l rpport(a5),a2
- movea.l packet(a5),a1
- movea.l conid(a5),a0
- moveq #0,d0
- bsr.w SetConsoleType ;SetConsoleType(0L, conid, packet, rpport)
-
- * Release resources we borrowed
- gwbfreepack:
- move.l packet(a5),d0 ;Did we allocate a packet?
- beq.b gwbfreeport ;nay, check for port to free
- movea.l d0,a1
- moveq #sp_SIZEOF,d0
- SYS FreeMem ;Else FreeMem(packet, sizeof(*packet))
-
- gwbfreeport:
- move.l rpport(a5),d0 ;if (rpport)...
- beq.w gwbdone ;nope
- bsr.w DeletePort ;Else DeletePort(rpport)
-
- * Finally, sanity check window bounds report string
- * d4 = length of report string according to Read()
- cmpi.l #9,d4 ;Less than 8 characters returned?
- ble.w gwbdone ;hmmm, phonky bounds report from DOS?
- lea rpstr(a5),a2 ;a2 = rpstr
- cmpi.b #';',4(a2) ;Matches a typical report template?
- bne.w gwbdone ;nope, got some weird junk back?
- cmpi.b #'r',-1(a2,d4.w) ;Last byte is 'r' for report?
- bne.w gwbdone ;Nope, message fubar!
-
- * Parse the height and width variables from the field now
- * Our report format looks like this in hex:
- * 9b 31 3b 31 3b y2 y1 3b x2 x1 20 72
- * Or in ascii:
- * <0x9b>1;1;20;77 r
- * Which would indicate a width of 77 cols and a height of 20 rows for
- * the current console device
- *
- * REGS: a2 points to beginning of 'r' terminated string
-
- lea 5(a2),a2 ;Point to first char of Y size
- moveq #0,d1 ;Clear out work reg
-
- * Convert ascii rows value to LONG, update host data
- move.b (a2)+,d1 ;Grab a Y
- subi.w #'0',d1 ;Less ascii offset
- cmpi.b #';',(a2) ;Any more Y digits?
- beq.b 1$ ;Nope
- mulu #10,d1 ;Else shift by 10
- add.b (a2)+,d1 ;Add least significant Y digit
- subi.b #'0',d1 ;Less ascii offset
- cmpi.b #';',(a2) ;Any more Y digits?
- beq.b 1$ ;Nope
- mulu #$000a,d1 ;Else shift by 10
- add.b (a2)+,d1 ;Add least significant Y digit
- subi.b #'0',d1 ;Less ascii offset
- ;We'll assume screen height < 999 rows
- 1$
- * Convert ascii columns value to LONG, update host data
- addq.w #1,a2 ;Move past the ';' separator
- moveq #0,d2 ;Zap work reg
- move.b (a2)+,d2 ;Grab msd of X
- cmpi.b #' ',d2 ;Premature end?
- beq.w gwbdone ;Huh, must be garbage - don't update VPARMS
- cmpi.b #';',d2 ;Also a possible error
- beq.w gwbdone
- cmpi.b #'r',d2 ;And what about this?
- beq.w gwbdone
-
- subi.b #'0',d2 ;Okay, adjust ascii offset
- cmpi.b #' ',(a2) ;Hit end of report?
- beq.b 2$ ;Yep
- mulu #$000a,d2 ;Else shift by 10
- add.b (a2)+,d2 ;Add next digit
- subi.b #'0',d2 ;Ascii adjust
- cmpi.b #' ',(a2) ;Hit end of report?
- beq.b 2$ ;Yep
- mulu #$000a,d2 ;Else shift by 10
- add.b (a2),d2 ;Add next digit
- subi.b #'0',d2 ;Ascii adjust
-
- 2$
- * Finally, update parameters by reference
- movea.l height(a5),a0 ;Grab height VPARM
- move.l d1,(a0) ;*height = d1
- movea.l width(a5),a0 ;Grab width VPARM
- move.l d2,(a0) ;*width = d2
-
- gwbdone:
- movem.l (sp)+,d2-d4/a2
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * void __asm SetConsoleType(flag, id, packet, port)
- * register __d0 long flag;
- * register __a0 struct Process *id;
- * register __a1 struct StandardPacket *packet;
- * register __a2 struct MsgPort *port;
- *
- * Flag = 1L -- Raw mode
- * = 0L -- Cooked mode
- * --------------------------------------------------------------------- *
- XDEF SetConsoleType
- SetConsoleType:
- movem.l a3/a5,-(sp)
-
- movea.l a0,a3 ;Copy process pointer
- movea.l a1,a5 ;Copy packet pointer
- lea sp_Pkt(a5),a0 ;a0 = &packet->sp_Pkt
- move.l a0,sp_Msg+LN_NAME(a5) ;p->sp_Msg.mn_Node.ln_Name = &p->sp_Pkt
- lea sp_Msg(a5),a0 ;a0 = &packet->sp_Msg
- move.l a0,sp_Pkt+dp_Link(a5) ;p->sp_Pkt.dp_Link = &p->sp_Msg
- move.l a2,sp_Pkt+dp_Port(a5) ;p->sp_Pkt.dp_Port = replyport
- move.l #ACTION_SCREEN_MODE,sp_Pkt+dp_Type(a5) ;Set function
-
- tst.w d0 ;On or Off?
- beq.w 1$
- move.l #-1,sp_Pkt+dp_Arg1(a5) ;RAW ON
- bra.b 2$
- 1$
- clr.l sp_Pkt+dp_Arg1(a5) ;RAW OFF
- 2$
- movea.l a3,a0
- movea.l a5,a1
- SYS PutMsg,4 ;PutMsg(proc, packet)
-
- movea.l a2,a0
- SYS WaitPort ;WaitPort(port)
- movea.l a2,a0
- SYS GetMsg ;(void)GetMsg(port)
-
- movem.l (sp)+,a3/a5
- rts
-
- * ------------------------------------------------------------------------- *
- * struct MsgPort *CreatePort(name, pri) (a0/d0)
- * ------------------------------------------------------------------------- *
- XDEF CreatePort
- CreatePort:
- movem.l d5/d7/a2/a5,-(sp)
-
- move.l a0,a5 ;Save Name
- move.l d0,d5 ;Save Pri
-
- * Allocate a free signal, crap out if we can't
- moveq #-1,d0
- SYS AllocSignal,4
- cmp.l #-1,d0 ;Did we get a signal?
- bne.b cpgotsig ;Yep
- moveq #0,d0 ;Otherwise return NULL
- bra.w cpdone
-
- cpgotsig:
- move.l d0,d7 ;Save our signal
-
- * Allocate memory for MsgPort
- moveq.l #MP_SIZE,d0 ;Size of MsgPort
- move.l #MEMF_PUBLIC!MEMF_CLEAR,d1 ;Type of memory
- SYS AllocMem ;Allocate it
- tst.l d0 ;Did we get it?
- bne.b cpgotport ;Yep
-
- move.l d7,d0 ;Otherwise crap out, free signal
- SYS FreeSignal
- moveq #0,d0 ;Return NULL
- bra.w cpdone
-
- cpgotport:
- move.l d0,a2 ;This is our new port!
- move.l a5,LN_NAME(a2) ;port->mp_Node.ln_Name = name
- move.b d5,LN_PRI(a2) ;port->mp_Node.ln_Pri = priority
- move.b #NT_MSGPORT,LN_TYPE(a2) ;port->mp_Node.ln_Type = NT_MSGPORT
- move.b #PA_SIGNAL,MP_FLAGS(a2) ;port->mp_Flags = PA_SIGNAL
- move.b d7,MP_SIGBIT(a2) ;port->mp_SIGBIT = sigBit
- suba.l a1,a1
- SYS FindTask
- move.l d0,MP_SIGTASK(a2) ;port->mp_SIGTASK = FindTask(0L)
-
- cmpa.l #0,a5 ;Is this a new name?
- beq.b cpnoname ;Nope, add it to the msg list
-
- movea.l a2,a1
- SYS AddPort ;Otherwise add this port
- move.l a2,d0 ;Return port pointer
- bra.b cpdone
-
- cpnoname:
- * Initialized New List head
- lea MP_MSGLIST(a2),a0 ;a0 = &port->mp_MsgList
- move.l a0,(a0) ;list->lh_Head = list
- addq.l #4,(a0) ;list->lh_Head += 4L
- clr.l 4(a0) ;list->lh_Tail = 0L
- move.l a0,8(a0) ;list->lh_TailPred = list
- move.l a2,d0 ;Return port pointer
-
- cpdone:
- movem.l (sp)+,d5/d7/a2/a5
- rts
-
- * ------------------------------------------------------------------------- *
- * DeletePort(port)(d0)
- * ------------------------------------------------------------------------- *
- XDEF DeletePort
- DeletePort:
- move.l a5,-(sp)
-
- move.l d0,a5
- tst.l LN_NAME(a5) ;Is there a name?
- beq.s dpnoname
-
- move.l d0,a1
- SYS RemPort,4 ;RemPort(port)
-
- dpnoname:
- move.b #$ff,LN_TYPE(a5) ;port->mp_Node.ln_Type = 0xff
- move.l #-1,MP_MSGLIST(a5) ;port->mp_MsgList.lh_Head = -1L
-
- moveq #0,d0
- move.b MP_SIGBIT(a5),d0 ;d0 = port->mp_SigBit
- SYS FreeSignal,4 ;FreeSignal(d0)
-
- moveq #MP_SIZE,d0
- move.l a5,a1
- SYS FreeMem ;FreeMem(port, sizeof(*port))
-
- move.l (sp)+,a5
- rts
-
- * ------------------------------------------------------------------------
- * char *FibFileDate(fib_date)
- * register struct DateStamp *fib_date;
- *
- * Calculate date based on DateStamp structure and return a pointer
- * to the formatted date string.
- * ------------------------------------------------------------------------
- XDEF _FibFileDate
- _FibFileDate:
- link a5,#0
- movem.l d3-d7/a4,-(sp)
-
- movea.l 8(a5),a1 ;Grab datestamp pointer
- moveq #78,d7 ;Initial year = 1978
-
- move.l (a1),d5 ;days = fib_date->ds_Days
- blt.w ffdbaddate ;Hey! you can't be negative! Invalid date...
-
- * Determine what year it is
- divu #1461,d5
- move.l d5,d0 ;Stash it
- ext.l d5
- lsl.l #2,d5
- add.l d5,d7 ;year += (days / 1461) * 4
-
- * Count how many months into that year
- ffdgetmo:
- swap d0 ;days %= 1461
- move.w d0,d5
-
- 1$ tst.w d5 ;Out of days yet?
- beq.b 3$ ;Yep, done here
-
- move.w #365,d6 ;Else month_days = 365
- move.w d7,d0 ;Grab year
- andi.w #3,d0 ;if (year & 3) == 0 Leap year?
- bne.b 2$ ;Nope
- addq.w #1,d6 ;Otherwise bump month_days
-
- 2$ cmp.w d6,d5 ;is day < month_days?
- blt.b 3$ ;yep, done here
- sub.w d6,d5 ;otherwise day -= month_days
-
- addq.l #1,d7 ; year++
- bra.b 1$
- 3$
-
- * Count how many days into that month of that year
- ffdgetday:
- ;for (i = 0, day++; i < 12; i++)
- moveq #0,d4 ;current month = 0
- moveq #0,d6 ;Zap hinybs
- addq.w #1,d5
- lea _dayspermonth(a4),a0
-
- 1$
- move.b 0(a0,d4.w),d6 ;month_days = dayspermonth[i]
-
- cmpi.w #1,d4 ;if (i == 1 && (year & 3) == 0)
- bne.b 2$
- move.w d7,d0
- andi.w #3,d0
- bne.b 2$
- addq.w #1,d6 ;month_days++
-
- 2$ cmp.w d6,d5 ;if (day <= month_days)
- ble.b 4$ ;Break out, found the right month
-
- sub.w d6,d5 ;Else, day -= month_days
-
- addq.w #1,d4 ;i++
- 3$ cmpi.w #12,d4 ;Done all months yet?
- blt.b 1$ ;Nope
-
- 4$
- ffdprint:
- 1$ cmpi.l #99,d7 ;while (year >= 100)
- ble.b 2$
- subi.l #100,d7 ;year -= 100
- bra.b 1$
- 2$
- ;asprintf(datestr, "%02d-%02d-%02d %02d:%02d:%02d", i + 1, day, year, hour, min, sec)
- move.l 8(a1),d0 ;sec = fib_date->ds_Tick / 50;
- divu #50,d0
- move.w d0,-(sp) ;Push secs
-
- moveq #0,d0 ;Zap reg
- move.w 6(a1),d0 ;min = fib_date->ds_Minute
- move.w d0,d1 ;Clone it
- divu #60,d0
- move.w d0,d3 ;hour = min / 60
- mulu #60,d0
- sub.w d0,d1 ;min -= hour * 60
- move.w d1,-(sp) ;Push mins
-
- move.w d3,-(sp) ;Push hours
- addq.w #1,d4 ;Push day of month (offset by 1!)
- move.w d5,-(sp) ;Push month
- move.w d4,-(sp)
- move.w d7,-(sp) ;Push year
- pea _datepat(a4) ;Push the format pattern
- pea _datestr(a4) ;Push destination buffer
- jsr _asprintf
- lea 20(sp),sp
- lea _datestr(a4),a0
- move.l a0,d0 ;return((char *)&datestr[0])
-
- ffddone:
- movem.l (sp)+,d3-d7/a4
- unlk a5
- rts
-
- ffdbaddate:
- lea _baddatestr(a4),a0 ;return (" <Invalid Date> ");
- move.l a0,d0
- bra.b ffddone
-
- *----------------------------------------------------------------------
- * LONG iswild(name)
- * char *name;
- *
- * Search a string for wild characters, return 1 if found
- *----------------------------------------------------------------------
- XDEF _iswild
- _iswild:
- movea.l 4(sp),a0 ;Grab string pointer
- moveq #0,d0 ;Clear out our character register
- ischk1:
- move.b (a0)+,d0 ;Grab a char
- beq.b iwdone ;Might be end of string?
- cmpi.b #'*',d0 ;Is it *?
- beq.b iswdone ;yep, is wild
- cmpi.b #'?',d0 ;Is it a qmark
- bne.b ischk1 ;Nope, check next character
-
- iswdone:
- moveq #1,d0
- iwdone:
- rts
-
-
- * ------------------------------------------------------------------------
- ; Compare a wild card name with a normal name
- ; LONG wildmatch (name, wild)
- ; char *name, *wild;
- * ------------------------------------------------------------------------
- XDEF _wildmatch
- _wildmatch:
- link a5,#-64
- movem.l d3/a2-a3,-(sp)
-
- movea.l 8(a5),a2 ;Grab name
- movea.l 12(a5),a3 ;Grab pattern
- lea -64(a5),a0 ;back[0][0]
- lea -60(a5),a1 ;back[0][1]
-
- moveq #0,d3 ;bi = 0
-
- wmloop1:
- tst.b (a2) ;End of name?
- bne.b wmnoteon
- tst.b (a3) ;End of pattern?
- beq.w wmmatched ;Yep, we matched
-
- wmnoteon:
- cmpi.b #'*',(a3) ;Is it a splat?
- bne.b wmnotstar ;Nope, maybe '?'
-
- cmpi.w #64,d3 ;Have we hit max expression depth?
- beq.w wmnomatch ;Yep, ran out of room in recursion table
-
- ;back[bi][0] = w
- move.l a3,0(a0,d3.w) ;Stash pointer to this '*' in table
-
- ;back[bi][1] = n
- move.l a2,0(a1,d3.w)
-
- addq.w #8,d3 ;++bi
- addq.w #1,a3 ;++w
- bra.b wmloop1 ;Check next
-
- wmgoback:
- subq.w #8,d3 ;--bi
- move.l a0,d0
- wmback1:
- tst.w d3 ;while (bi >= 0 && *back[bi][1] == '\x0')
- blt.b wmbacked
- movea.l 0(a1,d3.l),a0
- tst.b (a0)
- bne.b wmbacked
-
- subq.w #8,d3 ;--bi
- bra.b wmback1
-
- wmbacked:
- tst.w d3 ;if (bi < 0)
- blt.b wmnomatch ;return (0)
-
- movea.l d0,a0
- movea.l 0(a0,d3.w),a3 ;w = back[bi][0] + 1
- addq.w #1,a3
-
- addq.l #1,0(a1,d3.w)
- movea.l 0(a1,d3.l),a2 ;n = ++back[bi][1]
-
- addq.w #8,d3 ;++bi
- bra.b wmloop1
-
- wmnotstar:
- cmpi.b #'?',(a3) ;Is it '?'
- bne.b wmnotqmark
-
- tst.b (a2) ;Reached end of string?
- bne.b wmincpoint ;Nope, move on to next char
-
- tst.w d3 ;Are we at top level of expression?
- beq.b wmnomatch ;Yep, expression didn't match
- bra.b wmgoback ;Otherwise pop a level and try to match
-
- wmnotqmark:
- move.b (a2),d0 ;Grab a char from bstr
- cmpi.b #$40,d0 ;less than @ character?
- bls.b 1$ ;Yep
- cmpi.b #$5a,d0 ;Greater than Z?
- bhi.b 1$ ;Yep
- addi.b #$20,d0
- 1$
- move.b (a3),d1 ;Grab a char from bstr
- cmpi.b #$40,d1 ;less than @ character?
- bls.b 2$ ;Yep
- cmpi.b #$5a,d1 ;Greater than Z?
- bhi.b 2$ ;Yep
- addi.b #$20,d1
- 2$
- cmp.b d0,d1 ;*n = *w?
- beq.b wmincpoint ;Yep, move on past
-
- tst.w d3 ;Are we at top expression level?
- beq.b wmnomatch ;Yep, they didn't match
- bra.b wmgoback ;Nope, process next part
-
- wmincpoint:
- tst.b (a2) ;Done with name?
- beq.b wmnamend ;Yep
- addq.w #1,a2 ;Otherwise increment name pointer
-
- wmnamend:
- tst.b (a3) ;End of pattern?
- beq.b wmmatched ;Yep, we matched
- addq.w #1,a3 ;Otherwise inc wild pointer, match next char
- bra.w wmloop1
-
- wmmatched:
- moveq #1,d0
- bra.b wmdone
-
- wmnomatch:
- moveq #0,d0
-
- wmdone:
- movem.l (sp)+,d3/a2-a3
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * void SortFibs (keytype, direction, fibheadp)
- * d0 d1 a0
- * int keytype;
- * struct FibEntry *fibheadp;
- *
- * Selection sort a linked list of FibEntrys based on a keycode *
- * --------------------------------------------------------------------- *
- XDEF _SortFibs
- _SortFibs:
- link a5,#0
- movem.l d2-d4/a2-a3/a6,-(sp)
-
- movem.l 8(a5),d0-d1/a0
-
- move.l d0,d2 ;Save keytype
- move.l d1,d4 ;Save direction of sort
- movea.l a0,d3 ;Save fibheadp
- movea.l a0,a2 ;a2 = a0 = i
-
- sfILoop:
- cmp.l (a2),d3 ;i->NextFib != fibheadp?
- beq.b sfdone ;Nope, wrapped around to start
- movea.l a2,a6 ;k = i
- movea.l (a2),a3 ;j = i->NextFib
-
- sfJLoop:
- cmp.l a3,d3 ;j != fibheadp?
- beq.b sfJdone ;Nope compared them all, see if swapped any
- movea.l 8(a6),a0 ;a0 = k->Fibp
- movea.l 8(a3),a1 ;a1 = j->Fibp
- move.l d2,d0 ;d0 = keytype
- jsr _CompFibs ;d0 = CompFibs(keytype, k->Fibp, j->Fibp)
- tst.w d4 ;Reverse sort?
- beq.b 1$ ;Nope
- bchg.l #0,d0 ;Else reverse sense of return
- 1$
- tst.l d0 ;Return != 0?
- beq.b sfNextJ ;Nope, these two are in order
- movea.l a3,a6 ;else k = j, this is new swap
-
- sfNextJ:
- movea.l (a3),a3 ;j = j->NextFib
- bra.b sfJLoop ;Check bounds
-
- sfJdone:
- cmpa.l a6,a2 ;k != i, did we swap?
- beq.b sfNextI ;Nope, i was in correct position already
- move.l 8(a6),d0
- move.l 8(a2),8(a6)
- move.l d0,8(a2) ;Else SwapFibs (k, i)
-
- sfNextI:
- movea.l (a2),a2 ;i = i->NextFib
- bra.b sfILoop ;Check bounds
-
- sfdone:
- movem.l (sp)+,d2-d4/a2-a3/a6
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * int CompFibs (keytype, a, b)
- * d0 a0 a1
- * int keytype;
- * struct FileInfoBlock *a, *b;
- *
- * Used by SortFibs to determine precedence of Fibs.
- * --------------------------------------------------------------------- *
- XDEF _CompFibs
- _CompFibs:
- tst.w d0 ;Alphabetize?
- bne.b cfnalpha ;Nope
-
- * Compare lexigraphically, ignoring case differences
- cfalpha:
- lea fib_FileName(a0),a0 ;a = &Fipb->fib_FileName
- lea fib_FileName(a1),a1 ;b = &Fipb->fib_FileName
-
- ; for(; *a && tolower(*a) == tolower(*b); a++, b++);
- lccstart:
- tst.b (a0) ;Is there a char here at source?
- beq.b lcceostr ;Nope, fell off the end
-
- move.b (a1)+,d1 ;Grab a char from bstr
- cmpi.b #$40,d1 ;less than @ character?
- bls.b 1$ ;Yep
- cmpi.b #$5a,d1 ;Greater than Z?
- bhi.b 1$ ;Yep
- addi.b #$20,d1
- 1$
- move.b (a0)+,d0 ;Grab a char from astr
- cmpi.b #$40,d0 ;less than @ character?
- bls.b 2$ ;Yep
- cmpi.b #$5a,d0 ;Greater than Z?
- bhi.b 2$ ;Yep
- addi.b #$20,d0
- 2$
- cmp.b d0,d1 ;are they the same?
- beq.b lccstart ;Yep, compare next pair of chars
-
- lcceostr:
- sub.b d1,d0 ;return(tolower(*astr) - tolower(*bstr))
- bgt.b cftrue ; > 0?, return TRUE
- bra.b cffalse ;Else return FALSE
-
- cfnalpha:
- subq.w #1,d0 ;Size?
- bne.b cfnsize ;Nope
-
- * Compare fib_Sizes
- move.l fib_Size(a1),d0 ;d0 = bfib->fib_Size
- cmp.l fib_Size(a0),d0 ;a->fib_Size > b->fib_Size?
- blt.b cftrue ;Yep, return TRUE
- bgt.b cffalse ;<, return FALSE
- bra.b cfalpha ;Else it's a tie, alphabetize
-
- cfnsize:
- subq.w #1,d0 ;Time?
- bne.b cffalse ;Nope, an error!
-
- * Compare fib_DateStamps
- lea fib_DateStamp(a0),a0 ;a = &afib->fib_DateStamp
- lea fib_DateStamp(a1),a1 ;b = &bfib->fib_DateStamp
- move.l ds_Days(a1),d0 ;d0 = bdate->ds_Days
- cmp.l ds_Days(a0),d0 ;a->ds_Days > b->ds_Days?
- blt.b cftrue ;Yep, a is older
- bgt.b cffalse ;Else if a < b, b is older
- ;Else they are the same day, check min/tick
- move.l ds_Minute(a0),d0
- sub.l ds_Minute(a1),d0 ;d0 = amin - bmin
- muls #3000,d0 ; * 3000
- add.l ds_Tick(a0),d0
- sub.l ds_Tick(a1),d0 ; + atick - btick
- bgt.b cftrue ;Hey, a > b
- blt.b cffalse ;a < b, return false
- bra.b cfalpha ;Else its the same date, alphabetize
-
- cftrue:
- moveq #1,d0
- rts
- cffalse:
- moveq #0,d0
- rts
-
- * --------------------------------------------------------------------- *
- SECTION __MERGED,DATA
- * --------------------------------------------------------------------- *
- XDEF _dayspermonth
- _dayspermonth:
- dc.b 31,28,31,30,31,30,31,31,30,31,30,31
- XDEF _datepat
- _datepat:
- dc.b '%02d-%02d-%02d %02d:%02d:%02d',0
- CNOP 0,2
- XDEF _baddatestr
- _baddatestr:
- dc.b '00-00-00 00:00:00',0
- CNOP 0,2
-
- XDEF gwbrstr
- gwbrstr:
- dc.b $9b,'0 q'
-
- * --------------------------------------------------------------------- *
- SECTION __MERGED,BSS
- * --------------------------------------------------------------------- *
- XDEF _datestr
- _datestr:
- ds.b 40
-
- * --------------------------------------------------------------------- *
- END
- * --------------------------------------------------------------------- *
-