Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (04/11/90)
Submitted-by: kim@uts.amdahl.com (Kim E. DeVaughn)
Posting-number: Volume 90, Issue 132
Archive-name: unix/ls-3.1/part02
#!/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 2 (of 3)."
# Contents: src/lssup.a
# Wrapped by tadguy@xanth on Tue Apr 10 17:22:48 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'\" \(33907 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* --------------------------------------------------------------------- *
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_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
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 IoErr
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 @CleanUp
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 NoFindFmtStr
X XREF NoRAMMsg
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 d3/a2-a3,-(sp)
X
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 cmpi.b #$40,d0 ;less than @ character?
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 move.b (a3),d1 ;Grab a char from bstr
X cmpi.b #$40,d1 ;less than @ character?
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)+,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, or 2:
X* 0=alpha, 1=size, 2=date
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 & MIXFILEDIRS?
X bne.s cftstsort ;Yep, 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, 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++);
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 cmpi.b #$40,d1 ;less than @ character?
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 move.b (a0)+,d0 ;Grab a char from astr
X cmpi.b #$40,d0 ;less than @ character?
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 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 bgt.s cftrue ;Yep, return TRUE
X blt.s cffalse ;<, return FALSE
X bra cfalpha ;Else it's a tie, alphabetize
X
Xcfnsize:
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 beq cfalpha ;its the same date?, alphabetize
X blt.s cffalse
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 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 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 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 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 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 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 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* VOID NoMemExit(VOID)
X* --------------------------------------------------------------------- *
X XDEF @NoMemExit
X@NoMemExit:
X moveq #103,d1
X moveq #20,d0
X lea NoRAMMsg(a4),a0
X jsr @CleanUp
X rts
X
X* --------------------------------------------------------------------- *
X* VOID NoFileExit(name)
X* a0
X* BYTE *name;
X* --------------------------------------------------------------------- *
X XDEF @NoFileExit
X@NoFileExit:
X movem.l d2-d4/a6,-(sp)
X
X move.l a0,d2 ;Save name
X SYS IoErr,DOSBase(a4) ;Get IoError status
X move.l d0,d3 ;Save it
X
X move.l #300,d0
X jsr @myalloc
X move.l d0,d4 ;d3 = myalloc( 300 )
X bne.s 1$ ;Got it!
X jsr @NoMemExit ;else exit with No Ram message
X bra.s 2$
X1$
X move.l d2,-(sp)
X pea NoFindFmtStr(a4)
X move.l d4,-(sp)
X jsr asprintf ;asprintf(tstr, NoFindFmtStr, name)
X lea 12(sp),sp
X
X move.l d3,d1
X moveq #20,d0
X movea.l d4,a0
X jsr @CleanUp ;CleanUp(tstr, 20L, IoErr())
X ; a0 d0 d1
X move.l d4,a0
X jsr @myfree ;free (tstr)
X2$
X movem.l (sp)+,d2-d4/a6
X rts
X
X* --------------------------------------------------------------------- *
X END
X* --------------------------------------------------------------------- *
END_OF_FILE
if test 33907 -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 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 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.