home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
newc_dev
/
ls40.lzh
/
src
/
lssup.a
< prev
next >
Wrap
Text File
|
1990-05-10
|
35KB
|
1,313 lines
* --------------------------------------------------------------------- *
* lssup.a - Assembly support routines for ls.c
* Written by Justin V. McCormick 89-07-24
* Modified for use in v4.0k by Kim E. DeVaughn - 05/11/90
* --------------------------------------------------------------------- *
IFD CAPE
CSYMFMT
BASEREG B
SMALLOBJ
ADDSYM
OPTIMON
IDNT "lssup.a"
ENDC
SYS MACRO *
IFGT NARG-2
FAIL !!!
ENDC
IFEQ NARG-2
MOVE.L \2,a6
ENDC
JSR LVO\1(a6)
ENDM
XLVO MACRO *
XREF LVO\1
ENDM
; Equates
fib_DiskKey EQU $0
fib_DirEntryType EQU $4
fib_FileName EQU $8
fib_Size EQU $7C
fib_NumBlocks EQU $80
fib_DateStamp EQU $84
fib_SIZEOF EQU $104
ds_Days EQU $0
ds_Minute EQU $4
ds_Tick EQU $8
LH_HEAD EQU $0
LN_PRED EQU $4
LN_SUCC EQU $0
fe_Node EQU $0
fe_Fib EQU $8
pr_ConsoleTask EQU $A4
MEMF_CLEAR EQU $10000
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
* Library offsets
XLVO AddPort
XLVO AddTail
XLVO AllocMem
XLVO AllocSignal
XLVO CopyMem
XLVO Debug
XLVO Examine
XLVO FindTask
XLVO FreeMem
XLVO FreeSignal
XLVO GetMsg
XLVO Input
XLVO Insert
XLVO IsInteractive
XLVO Output
XLVO ParentDir
XLVO PutMsg
XLVO RawDoFmt
XLVO Read
XLVO RemPort
XLVO WaitForChar
XLVO WaitPort
XLVO Write
XLVO UnLock
* External constants
XREF @AllocFib
XREF @stpcpy
XREF @strcat
XREF @strlen
XREF baddatestr
XREF badtimestr
XREF ColonStr
XREF datepat
XREF dayspermonth
XREF DOSBase
XREF gwbrstr
XREF LSFlags
XREF RamNameStr
XREF SlashStr
XREF sortkey
XREF timepat
SECTION CODE
* --------------------------------------------------------------------- *
* VOID *myalloc (LONG)
* d0 d0
* --------------------------------------------------------------------- *
XDEF @myalloc
@myalloc:
movem.l d2/a6,-(sp)
addq.l #4,d0 ;Include sizeof(LONG)
move.l d0,d2 ;Copy to survive AllocMem
moveq #0,d1 ;MEMF_ANYTHING
SYS AllocMem,4 ;AllocMem(size + 4, 0L)
tst.l d0 ;Got it?
beq.s 1$
movea.l d0,a6 ;Copy pointer
move.l d2,(a6)+ ;Stash size in first 4 bytes
move.l a6,d0 ;return final pointer in d0
1$
movem.l (sp)+,d2/a6
rts
* --------------------------------------------------------------------- *
* VOID myfree (VOID *)
* a0
* --------------------------------------------------------------------- *
XDEF @myfree
@myfree:
move.l a6,-(sp)
lea -4(a0),a1 ;Put in sys reg
move.l (a1),d0 ;d0 = size to free
SYS FreeMem,4
movea.l (sp)+,a6
rts
* --------------------------------------------------------------------- *
* 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/a6,-(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/a6 ;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;
* a0 a1
* Find current console window, determine width and height
* in terms of current font, update width and height VPARMS passed.
* --------------------------------------------------------------------- *
height EQU -4
width EQU -8
conid EQU -12
packet EQU -16
rpport EQU -20
rpstr EQU -40
XDEF @GetWinBounds
@GetWinBounds:
link a5,#-44
movem.l d2-d4/a2/a6,-(sp)
move.l a0,width(a5) ;Save width/height pointers on stack
move.l a1,height(a5)
SYS Input,DOSBase(a4) ;Grab Input filehandle
move.l d0,d1
SYS IsInteractive ;IsInteractive(Input())?
tst.l d0
beq.s gwbnowbrep ;Nope, can't get a bounds report
SYS Output
move.l d0,d1
SYS IsInteractive ;IsInteractive(Output())?
tst.l d0
beq.s gwbnowbrep ;Nope, don't clutter output stream
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
tst.l conid(a5) ;Is there really a console there?
bne.s gwbgotcon ;Yep
gwbnowbrep:
* Else we cannot get a window bounds report from this source
moveq #23,d1 ;return H=23
moveq #77,d2 ; W=77
bra gwbupdate
gwbgotcon:
moveq #0,d4 ;Clear our success status register
moveq #0,d0
movea.l d0,a0
jsr CreatePort
move.l d0,rpport(a5) ;rpport = CreatePort(0L, 0L)
beq gwbdone ;Oops, no signals or ram available!
moveq #sp_SIZEOF,d0
jsr @myalloc
move.l d0,packet(a5) ;packet = AllocBlock(sizeof(*packet))
beq 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
jsr SetConsoleType ;SetConsoleType(1L, conid, packet, rpport)
* Request a window bounds report
SYS Output,DOSBase(a4)
move.l d0,d1
moveq #4,d3
lea gwbrstr(a4),a0
move.l a0,d2
SYS Write,DOSBase(a4) ;Write(Output(), "\2330 q", 4L);
cmpi.l #$0004,d0 ;Did the console choke on it?
bne gwbsetcook ;hmmm, see if we can back out gracefully
* Read the report string into stack buffer, if there is one
move.l #10000,d2
SYS Input
move.l d0,d1
SYS WaitForChar ;WaitForChar(Input(), 10000L) (.01 secs)
tst.l d0 ;Did we get the report?
beq gwbsetcook ;Nope, must not be a report coming
SYS Input
move.l d0,d1
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
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
jsr SetConsoleType ;SetConsoleType(0L, conid, packet, rpport)
* Release resources we borrowed
gwbfreepack:
move.l packet(a5),d0 ;Did we allocate a packet?
beq.s gwbfreeport ;nay, check for port to free
movea.l d0,a0
jsr @myfree ;Else FreeBlock(packet)
gwbfreeport:
move.l rpport(a5),d0 ;if (rpport)...
beq gwbdone ;nope
jsr 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 gwbdone ;hmmm, phonky bounds report from DOS?
lea rpstr(a5),a2 ;a2 = rpstr
cmpi.b #';',4(a2) ;Matches a typical report template?
bne gwbdone ;nope, got some weird junk back?
cmpi.b #'r',-1(a2,d4.w) ;Last byte is 'r' for report?
bne 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
addq.w #5,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.s 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.s 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 gwbdone ;Huh, must be garbage - don't update VPARMS
cmpi.b #';',d2 ;Also a possible error
beq gwbdone
cmpi.b #'r',d2 ;And what about this?
beq gwbdone
subi.b #'0',d2 ;Okay, adjust ascii offset
cmpi.b #' ',(a2) ;Hit end of report?
beq.s 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.s 2$ ;Yep
mulu #$000a,d2 ;Else shift by 10
add.b (a2),d2 ;Add next digit
subi.b #'0',d2 ;Ascii adjust
2$
gwbupdate:
* 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/a6
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 a2/a3/a5/a6,-(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 1$
move.l #-1,sp_Pkt+dp_Arg1(a5) ;RAW ON
bra.s 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)+,a2/a3/a5/a6
rts
* ------------------------------------------------------------------------- *
* struct MsgPort *CreatePort(name, pri) (a0/d0)
* ------------------------------------------------------------------------- *
XDEF CreatePort
CreatePort:
movem.l d5/d7/a2/a5/a6,-(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.s cpgotsig ;Yep
moveq #0,d0 ;Otherwise return NULL
bra cpdone
cpgotsig:
move.l d0,d7 ;Save our signal
* Allocate memory for MsgPort
moveq #MP_SIZE,d0 ;Size of MsgPort
jsr @myalloc ;Allocate it
tst.l d0 ;Did we get it?
bne.s cpgotport ;Yep
move.l d7,d0 ;Otherwise crap out, free signal
SYS FreeSignal
moveq #0,d0 ;Return NULL
bra 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.s 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.s 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/a6
rts
* ------------------------------------------------------------------------- *
* DeletePort(port)(d0)
* ------------------------------------------------------------------------- *
XDEF DeletePort
DeletePort:
movem.l a5/a6,-(sp)
move.l d0,a5
movea.l $4,a6
tst.l LN_NAME(a5) ;Is there a name?
beq.s dpnoname
move.l d0,a1
SYS RemPort ;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 ;FreeSignal(d0)
movea.l a5,a0
jsr @myfree ;FreeBlock(port)
movem.l (sp)+,a5/a6
rts
* ------------------------------------------------------------------------
* FibFileDate(fib_date, datestr, timestr)
* a0 a1 8(a5)
* struct DateStamp *fib_date;
* char *datestr, *timestr;
* 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/a2-a3/a6,-(sp)
movea.l a1,a3 ;a3 = datestr, 8(a5) = timestr
movea.l a0,a1 ;Grab datestamp pointer
moveq #78,d7 ;Initial year = 1978
move.l (a1),d5 ;days = fib_date->ds_Days
blt 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.s 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.s 2$ ;Nope
addq.w #1,d6 ;Otherwise bump month_days
2$ cmp.w d6,d5 ;is day < month_days?
blt.s 3$ ;yep, done here
sub.w d6,d5 ;otherwise day -= month_days
addq.l #1,d7 ; year++
bra 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.s 2$
move.w d7,d0
andi.w #3,d0
bne.s 2$
addq.w #1,d6 ;month_days++
2$ cmp.w d6,d5 ;if (day <= month_days)
ble.s 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 1$ ;Nope
4$
ffdprint:
1$ cmpi.l #99,d7 ;while (year >= 100)
ble.s 2$
subi.l #100,d7 ;year -= 100
bra 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
ext.l d0
move.l d0,-(sp) ;Push secs
move.l 4(a1),d0 ;min = fib_date->ds_Minute
move.l d0,d1 ;Clone it
divu #60,d0
moveq #0,d3
move.w d0,d3 ;hour = min / 60
mulu #60,d0
sub.w d0,d1 ;min -= hour * 60
move.l d1,-(sp) ;Push mins
move.l d3,-(sp) ;Push hours
pea timepat(a4) ;Push the format pattern
move.l 8(a5),-(sp) ;Push destination buffer, datestr
jsr asprintf
lea 20(sp),sp
move.l d5,-(sp) ;Push day
addq.w #1,d4 ;Push month (offset by 1!)
move.l d4,-(sp)
move.l d7,-(sp) ;Push year
pea datepat(a4) ;Push the format pattern
move.l a3,-(sp) ;Push destination buffer
jsr asprintf
lea 20(sp),sp
ffddone:
movem.l (sp)+,d3-d7/a2-a3/a6
unlk a5
rts
ffdbaddate:
lea badtimestr(a4),a1 ;stpcpy (timestr, "00:00:00");
movea.l 8(a5),a0
jsr @stpcpy
lea baddatestr(a4),a1 ;stpcpy (datestr, "00-00-00");
movea.l a3,a0
jsr @stpcpy
bra ffddone
*----------------------------------------------------------------------
* LONG iswild(name)
* char *name;
* a0
* Search a string for wild characters, return 1 if found
*----------------------------------------------------------------------
XDEF @iswild
@iswild:
moveq #0,d0 ;Clear out our character register
ischk1:
move.b (a0)+,d0 ;Grab a char
beq.s iwdone ;Might be end of string?
cmpi.b #'*',d0 ;Is it *?
beq.s iswdone ;yep, is wild
cmpi.b #'?',d0 ;Is it a qmark
bne.s 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;
; a0 a1
* ------------------------------------------------------------------------
XDEF @wildmatch
@wildmatch:
link a5,#-64
movem.l d2-d3/a2-a3,-(sp)
move.l LSFlags(a4),d2 ;Grab flags
movea.l a0,a2 ;Grab name
movea.l a1,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.s wmnoteon
tst.b (a3) ;End of pattern?
beq wmmatched ;Yep, we matched
wmnoteon:
cmpi.b #'*',(a3) ;Is it a splat?
bne.s wmnotstar ;Nope, maybe '?'
cmpi.w #64,d3 ;Have we hit max expression depth?
beq 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.s 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.s wmbacked
movea.l 0(a1,d3.l),a0
tst.b (a0)
bne.s wmbacked
subq.w #8,d3 ;--bi
bra.s wmback1
wmbacked:
tst.w d3 ;if (bi < 0)
blt.s 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.s wmloop1
wmnotstar:
cmpi.b #'?',(a3) ;Is it '?'
bne.s wmnotqmark
tst.b (a2) ;Reached end of string?
bne.s wmincpoint ;Nope, move on to next char
tst.w d3 ;Are we at top level of expression?
beq.s wmnomatch ;Yep, expression didn't match
bra.s wmgoback ;Otherwise pop a level and try to match
wmnotqmark:
move.b (a2),d0 ;Grab a char from bstr
move.b (a3),d1 ;Grab a char from astr
btst.l #21,d2 ;LSFlags & IGNORECASEWILD?
beq.s 2$ ;Nope, blow off lowercasing crap
cmpi.b #$40,d0 ;less than @ character? (for bstr)
bls.s 1$ ;Yep
cmpi.b #$5a,d0 ;Greater than Z?
bhi.s 1$ ;Yep
addi.b #$20,d0
1$
cmpi.b #$40,d1 ;less than @ character? (for astr)
bls.s 2$ ;Yep
cmpi.b #$5a,d1 ;Greater than Z?
bhi.s 2$ ;Yep
addi.b #$20,d1
2$
cmp.b d0,d1 ;*n = *w?
beq.s wmincpoint ;Yep, move on past
tst.w d3 ;Are we at top expression level?
beq.s wmnomatch ;Yep, they didn't match
bra.s wmgoback ;Nope, process next part
wmincpoint:
tst.b (a2) ;Done with name?
beq.s wmnamend ;Yep
addq.w #1,a2 ;Otherwise increment name pointer
wmnamend:
tst.b (a3) ;End of pattern?
beq.s wmmatched ;Yep, we matched
addq.w #1,a3 ;Otherwise inc wild pointer, match next char
bra wmloop1
wmmatched:
moveq #1,d0
bra.s wmdone
wmnomatch:
moveq #0,d0
wmdone:
movem.l (sp)+,d2-d3/a2-a3
unlk a5
rts
* --------------------------------------------------------------------- *
* BOOL CompFibs (keytype, a, b)
* d0 a0 a1
* LONG keytype;
* struct FileInfoBlock *a, *b;
*
* Used by SortFibs to determine precedence of Fibs.
* keytype is one of 0, 1, 2, or 3:
* 0=alpha, 1=size, 2=date, 3=diskkey
* --------------------------------------------------------------------- *
XDEF @CompFibs
@CompFibs:
movem.l d2-d3/a2,-(sp)
move.l d0,d2 ;Stash keytype
* Prioritize Dirs/Files?
move.l LSFlags(a4),d3 ;Grab flags
btst.l #17,d3 ;LSFlags & SEPFILESDIRS?
beq.s cftstsort ;No, don't bother comparing EntryTypes
move.l fib_DirEntryType(a0),d0
cmp.l fib_DirEntryType(a1),d0
blt.s 1$ ;a0 is < a1, (dir < file)
beq.s cftstsort ;a0 is == a1, try next test
moveq #0,d0 ;a0 is > a1, (file > dir)
bra.s 2$
1$
moveq #1,d0 ;greater than, (dir < file)
2$ btst.l #16,d3 ;LSFlags & FILESFIRST?
beq cfexit0 ;Nope, default Dirs first
bchg.l #0,d0 ;Else d0 ^= 1, reverse sense
bra cfexit0
* Both entries are the same type, now see about sorting them
cftstsort:
btst.l #6,d3 ;LSFlags & NOSORTFLAG set?
bne cffalse ;Yep, always AddTail to list
* Switch keytype
tst.w d2 ;Alphabetize?
bne.s cfnalpha ;Nope
* Compare lexigraphically, optionally 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++); [tolower() crap optional]
lccstart:
tst.b (a0) ;Is there a char here at source?
beq.s lcceostr ;Nope, fell off the end
move.b (a1)+,d1 ;Grab a char from bstr
move.b (a0)+,d0 ;Grab a char from astr
btst.l #20,d3 ;LSFlags & IGNORECASELIST?
beq.s 2$ ;Nope, blow off lowercasing crap
cmpi.b #$40,d1 ;less than @ character? (for bstr)
bls.s 1$ ;Yep
cmpi.b #$5a,d1 ;Greater than Z?
bhi.s 1$ ;Yep
addi.b #$20,d1
1$
cmpi.b #$40,d0 ;less than @ character? (for astr)
bls.s 2$ ;Yep
cmpi.b #$5a,d0 ;Greater than Z?
bhi.s 2$ ;Yep
addi.b #$20,d0
2$
cmp.b d0,d1 ;are they the same?
beq.s lccstart ;Yep, compare next pair of chars
lcceostr:
sub.b d1,d0 ;return([tolower](*astr) - [tolower](*bstr))
bgt.s cftrue ; > 0?, return TRUE
bra.s cffalse ;Else return FALSE
cfnalpha:
subq.w #1,d2 ;Size?
bne.s cfnsize ;Nope
* Compare fib_Sizes
move.l fib_Size(a0),d0 ;d0 = afib->fib_Size
cmp.l fib_Size(a1),d0 ;b->fib_Size < a->fib_Size?
blt.s cftrue ;Yep, return TRUE
bgt.s cffalse ;>, return FALSE
bra.s cfalpha ;Else it's a tie, alphabetize
cfnsize:
subq.w #1,d2 ;Date?
bne.s cfndate ;No
* Compare fib_DateStamps
lea fib_DateStamp(a0),a0 ;a = &afib->fib_DateStamp
lea fib_DateStamp(a1),a1 ;b = &bfib->fib_DateStamp
jsr @CompareDateStamps
tst.l d0
blt.s cftrue
bgt.s cffalse
bra.s cfalpha ;same date; alphabetize
cfndate:
*Compare fib_DiskKeys
move.l fib_DiskKey(a0),d0 ;d0 = afib->fib_DiskKey
cmp.l fib_DiskKey(a1),d0 ;b->fib_DiskKey < a->fib_DiskKey?
beq.s cfalpha ;shouldn't happen [bad filesys if so]
blt.s cffalse ;<, return FALSE
cftrue:
moveq #1,d0
bra.s cfexit
cffalse:
moveq #0,d0
cfexit:
btst.l #9,d3 ;LSFlags & REVFLAG?
beq.s 1$ ;Nope
bchg.l #0,d0 ;Else invert boolean result
1$
cfexit0:
movem.l (sp)+,d2-d3/a2
rts
* --------------------------------------------------------------------- *
* LONG CompareDateStamps(adate, bdate)
* d0 a0 a1
* struct DateStamp *adate, *bdate;
* --------------------------------------------------------------------- *
XDEF @CompareDateStamps
@CompareDateStamps:
move.l ds_Days(a0),d0 ;d0 = adate->ds_Days
sub.l ds_Days(a1),d0 ;b->ds_Days > a->ds_Days?
bne.s 1$ ;Return b->day - a->day
;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
1$
rts
* --------------------------------------------------------------------- *
* VOID InsertFibNode(hfib, newfib)
* a0 a1
* struct List *hfib;
* struct FibEntry *newfib;
*
* Compare data in newfib->Fib with nodes in the list until we
* find the insertion point.
* --------------------------------------------------------------------- *
XDEF @InsertFibNode
@InsertFibNode:
movem.l d2/a2-a3/a5/a6,-(sp)
move.l sortkey(a4),d2
movea.l a0,a3 ;a3 = hfib
movea.l a1,a2 ;a2 = newfib
movea.l LH_HEAD(a3),a5 ;afib = hfib->lh_Head
1$ tst.l fe_Node+LN_SUCC(a5) ;afib->fe_Node.mln_Succ != 0?
beq.s 4$
movea.l fe_Fib(a2),a1
movea.l fe_Fib(a5),a0
move.l d2,d0
jsr @CompFibs ;CompFibs(sortkey, afib->Fib, newfib->Fib)
tst.w d0
bne.s 4$
movea.l fe_Node+LN_SUCC(a5),a5 ;afib = afib->fe_Node.mln_Succ
bra 1$
4$ movea.l a3,a0 ;a0 = List *
movea.l a2,a1 ;a1 = Node *
movea.l fe_Node+LN_PRED(a5),a2 ;a2 = Pred *
SYS Insert,4 ;Insert(hfib, newfib, afib->fe_Node.mln_Succ)
movem.l (sp)+,d2/a2-a3/a5/a6
rts
* --------------------------------------------------------------------- *
* LONG FillFibEntry (headfib, fibp)
* a0 a1
* struct List *headfib;
* struct FileInfoBlock *fibp;
* --------------------------------------------------------------------- *
XDEF @FillFibEntry
@FillFibEntry:
movem.l a2-a3/a5/a6,-(sp)
movea.l a0,a2 ;a2 = head of list
movea.l a1,a3 ;a3 = fileinfoblock
jsr @AllocFib ;Allocate a new fib
tst.l d0 ;Got it?
beq.s 3$ ;Nope, return 0
movea.l d0,a5 ;a5 = tfibp = AllocFib()
move.l #fib_SIZEOF,d0
movea.l fe_Fib(a5),a1
movea.l a3,a0
SYS CopyMem,4 ;CopyMem(fibp, tfibp->Fib, sizeof(struct fib))
movea.l a5,a1
movea.l a2,a0
jsr @InsertFibNode ;InsertFibNode(headfib, tfibp)
moveq #1,d0 ;return(1)
3$
movem.l (sp)+,a2-a3/a5/a6
rts
* --------------------------------------------------------------------- *
XDEF @nullstub
@nullstub:
moveq #0,d0
rts
* --------------------------------------------------------------------- *
* LONG GetPathString (dest, src)
* d0 a0 a1
* BYTE *dest, *src;
* --------------------------------------------------------------------- *
XDEF @GetPathString
@GetPathString:
move.l a2,-(sp)
moveq #0,d0 ;Zero return dest length
* Find end of src string
movea.l a1,a2 ;Save src start address
1$ tst.b (a1)+ ;while (*src++ != 0)
bne.s 1$
* Work backwards till we find a ':' or a '/'
2$ move.b -(a1),d1 ;c = *(--src)
cmpi.b #':',d1 ;Hit a colon?
beq.s 4$ ;Yep, found our path end
cmpi.b #'/',d1 ;Hit a slash?
bne.s 3$ ;Nope, try next char
cmpa.l a2,a1 ;At first char?
beq.s 4$ ;Yep, leave the single slash
cmpi.b #'/',-1(a1) ;Next char back is also a '/'?
beq.s 4$ ;Yep, allow multiple slashes
subq.w #1,a1 ;Else backup to previous char, eliminate '/'
bra.s 4$
3$
cmpa.l a2,a1 ;Back at start of src?
bhi.s 2$ ;Nope, try previous src char
bra.s gpsdone ;Else no dest, return
4$
* Copy path portion to dest
gpscpy:
cmpa.l a2,a1 ;Past end address?
bcs.s gpsdone ;Yep, terminate
move.b (a2)+,(a0)+ ;Copy a char from src to dest
addq.w #1,d0 ;Bump dest length count
bra.s gpscpy ;Check end address
gpsdone:
clr.b (a0) ;Null terminate dest
movea.l (sp)+,a2
rts
* --------------------------------------------------------------------- *
* LONG GetFileString (dest, src)
* d0 a0 a1
* BYTE *dest, *src;
* --------------------------------------------------------------------- *
XDEF @GetFileString
@GetFileString:
move.l a2,-(sp)
moveq #0,d0 ;Zero return dest length
* Find end of src string
movea.l a1,a2 ;Save src start address
1$ tst.b (a1)+ ;while (*src++ != 0)
bne.s 1$
* Work backwards till we find a ':' or a '/'
2$ move.b -(a1),d1 ;c = *(--src)
cmpi.b #':',d1 ;Hit a colon?
beq.s 4$ ;Yep, found our path end
cmpi.b #'/',d1 ;Hit a slash?
beq.s 4$ ;Nope, try next char
3$
cmpa.l a2,a1 ;Back at start of src?
bhi.s 2$ ;Nope, try previous src char
bra.s gfscpy ;Else no path, entire src is filename
4$
addq.w #1,a1 ;Move past ':' or '/'
* Copy name portion to dest
gfscpy:
move.b (a1)+,(a0)+ ;Copy a char from src to dest
beq.s 2$
addq.w #1,d0 ;Bump dest length count
bra.s gfscpy ;Check end address
2$
movea.l (sp)+,a2
rts
* ------------------------------------------------------------------------- *
* BYTE *astrncpy(dst, src, len)
* d0/a0 a0 a1 d0
* Takes text in a1, copies d0 bytes to text in a0.
* a0 returns pointing to null at end of final text.
* Dest text is always null terminated.
* ------------------------------------------------------------------------- *
XDEF @astrncpy
@astrncpy:
1$ subq.l #1,d0 ;Dec count
blt.s 2$ ;Done!
move.b (a1)+,(a0)+ ;Copy a byte
bne.s 1$ ;Do until end of src or cnt < 0
2$
clr.b (a0) ;Null terminate dest
move.l a0,d0 ;Return in d0 also
rts
* ------------------------------------------------------------------------- *
* VOID amovmem(src, dst, len)
* a0 a1 d0
* Takes text in a0, copies d0 bytes to text in a1. Correctly handles
* overlapping memory.
* ------------------------------------------------------------------------- *
XDEF amovmem
amovmem:
cmpa.l a0,a1 ;Low to high or high to low?
bcs.s 2$ ;High to low, copy forward
adda.w d0,a0 ;Else start at end, copy backward
adda.w d0,a1
1$ move.b -(a0),-(a1)
subq.w #1,d0
bgt 1$
bra.s amdone
2$ move.b (a0)+,(a1)+
subq.w #1,d0
bgt 2$
amdone:
rts
* --------------------------------------------------------------------- *
* BYTE *aindex(BYTE *, BYTE);
* d0 a0 d0
* --------------------------------------------------------------------- *
XDEF @aindex
@aindex:
1$ cmp.b (a0),d0
beq.s aifound
tst.b (a0)+
beq.s ainomatch
bra 1$
ainomatch:
moveq #0,d0
rts
aifound:
move.l a0,d0
rts
* --------------------------------------------------------------------- *
* LONG MakePathString(lock, dest)
* a0 a1
* struct FileLock *lock;
* BYTE *dest;
*
* DESCRIPTION:
* Given text and a filelock, construct entire pathname and
* return in dest.
* --------------------------------------------------------------------- *
XDEF @MakePathString
@MakePathString:
movem.l d2-d5/d7/a2-a3/a6,-(sp)
* Grab pointer to lock and dest text to fill
move.l a0,d3 ;d3 = lock
movea.l a1,a2 ;a2 = dest
clr.b (a2) ;NULL terminate dest
moveq #0,d5 ;LockFlag = 0
* Allocate a FileInfoBlock for local use
move.l #fib_SIZEOF,d0
jsr @myalloc
move.l d0,d7 ;d7 = *fib
beq mpsfailed ;Whoops no mem? return!
movea.l DOSBase(a4),a6 ;DOSBase calls from here on
* while (lock != 0)
1$
tst.l d3 ;Got a lock?
beq.s mpsokay ;Nope, must be at root
* Examine the current lock
move.l d3,d1
move.l d7,d2
SYS Examine ;Examine(lock, fib)
tst.l d0 ;Okay?
beq.s mpsfailed ;Nope, some sort of dos failure?
movea.l d7,a1
cmpi.b #' ',fib_FileName(a1) ;if (fib->fib_FileName[0] >= ' ')
bcs.s 3$ ;Nope, don't bother inserting?
tst.b (a2) ;if (dest[0] != 0)
beq.s 2$
lea SlashStr(a4),a1
movea.l a2,a0
jsr @InsertPathString ;InsertPathString(dest, "/");
2$
movea.l d7,a1
lea fib_FileName(a1),a1
movea.l a2,a0
jsr @InsertPathString ;InsertPathString(dest, fib->fib_FileName)
3$
* Okay, move up one directory
move.l d3,d4 ;oldlock = lock
move.l d3,d1
SYS ParentDir
move.l d0,d3 ;lock = ParentDir(lock)
tst.w d5 ;LockFlag set?
bne.s 4$ ;Yep, unlock
moveq #1,d5 ;Else LockFlag = 1, unlock next time
bra 1$ ;Next directory up
4$
move.l d4,d1
SYS UnLock ;UnLock(oldlock)
bra 1$ ;Examine
mpsokay:
* See if root was RAM:, special case
movea.l d7,a1 ;a1 = fib
cmpi.b #' ',fib_FileName(a1) ;if (fib->fib_FileName[0] >= ' ')
bcc.s 1$ ;Yep, not 1.1/1.2 RAM:
lea RamNameStr(a4),a1 ;Else...
movea.l a2,a0
jsr @InsertPathString ;InsertPathString(dest, "RAM:")
bra.s mpsdone
1$
* Find last slash we tacked on, change to a colon, or, add a colon
moveq #'/',d0
movea.l a2,a0
jsr @aindex ;d0 = strchr(dest, '/')
tst.l d0 ;Do we have a slash?
beq.s 2$ ;Nope, at root....
movea.l d0,a0
move.b #':',(a0) ;Else change first '/' to a ':'
bra.s mpsdone
* No slash, must be locked at the root. Append a colon to the dest.
2$
lea ColonStr(a4),a1
movea.l a2,a0
jsr @strcat ;strcat (dest, ":")
bra.s mpsdone
* Come here if an error occured, return empty text to caller
mpsfailed:
clr.b (a2) ;dest[0] = (BYTE)0
moveq #0,d3 ;return (0L)
bra.s mpsdeall
* Come here if everything is okay, deallocate FileInfoBlock
mpsdone:
moveq #1,d3 ;return (1L)
mpsdeall:
tst.l d7 ;Did we allocate a fib?
beq.s mpsfinis ;nope
movea.l d7,a0 ;Else free the memory
jsr @myfree
mpsfinis:
move.l d3,d0 ;Put return value in d0
movem.l (sp)+,d2-d5/d7/a2-a3/a6
rts
* --------------------------------------------------------------------- *
* VOID InsertPathString(dest, source)
* a0 a1
* BYTE *dest, *source;
*
* DESCRIPTION:
* Insert source text into dest text.
* Special case for source length == 0, source must be RAM.
* --------------------------------------------------------------------- *
XDEF @InsertPathString
@InsertPathString:
movem.l d7/a2-a3,-(sp)
movea.l a1,a3 ;a3 = source
move.l a0,a2 ;a2 = dest
movea.l a3,a0
jsr @strlen
move.l d0,d7 ;d7 = strlen(source)
1$ movea.l a2,a0
jsr @strlen ;d0 = strlen(dest)
addq.w #1,d0 ;Bump the length to include zero byte at end
movea.l a2,a1
adda.w d7,a1 ;Push dest + slen
movea.l a2,a0 ;Push dest
jsr amovmem ;amovmem(dest, dest + slen, strlen(dest) + 1)
move.w d7,d0
movea.l a2,a1
movea.l a3,a0
jsr amovmem ;amovmem(source, dest, slen)
movem.l (sp)+,d7/a2-a3
rts
* --------------------------------------------------------------------- *
END
* --------------------------------------------------------------------- *