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.