***************************************************************************** * * RemLib.asm by HEIKO RATH * copyright 1987/88 by the Software Brewery * * The purpose of this program is to remove a library from the librarylist. * To be save, it only removes librarys with an OpenCnt of 0. * To get a list of all librarys use RemLib without an argument. * Heiko Rath * Version 1.00 - printed all libraries with one Write (with many libs -> GURU) * Version 1.01 - prints every row with an extra Write * Version 1.05 - now features positive and negative size of library * Version 1.10 - now stops on CTRL-C * Version 1.11 - worked on error texts * * * This program is * * Copyright (c) 1988 by Heiko Rath and the Software Brewery. * * It may be freely distributed for non-profit only. * The distribution must contain ALL parts, in this case the following * files: * * RemLib * RemLib.asm * * Putting it on a commercial product is usually as easy as sending * a letter to the author. * ***************************************************************************** *______ / *______\O - The Software Brewery - * \\ * o Sparkling, fresh software from West-Germany * * @@@@@ Straight from the bar to your Amiga * |~~~|\ * | | |/ * |___| With our regards to the Software Distillery * *Christian Balzer alias , Lattice C, user interfaces, beer addict. *Heiko Rath alias
, Assembler, ROM-Kernal stuff, Marabou & beer addict. *Ralf Woitinas alias RAF, Assembler, anything, Ray-Tracing addict. *Andrew Kopp alias Charlie, Aztec C, Hardware & communications, beer addict. *Armin Sparr alias MARVIN, Aztec C, ARexx macros, Campari addict. *Christof Bonnkirch alias KEY, Aztec C, Hardware & Devices, beer addict. * *Beverages: Altenmuenster Brauer Bier, Urfraenkisches Landbier, Jever. * *Send exotic drinks, mail, comments and flames to: * *The Software Brewery *Christian Balzer UUCP: decwrl!frambo.dec.com!schabacker *Im Wingertsberg 45 ARPA: schabacker@frambo.dec.com *D-6108 Weiterstadt CIS : 71001,210 (be brief!) *WEST GERMANY (F.R.G.) Fone: +49 6150 4151 (18:00-21:00 CET!) * * *Send the above stuff, beautiful girls and of course MARABOU-CHOCOLATE to: * *Heiko Rath (HHHEEELLLPPP, I'm running out of MARABOU chocolate!!!!!!!) *Raiffeisenstr.10a *D-6108 Weiterstadt *WEST GERMANY (F.R.G.) * Version MACRO dc.b '1.11' ENDM ExecBase Equ 4 *** *** Exec Offsets: *** OpenLibrary Equ -552 ;OpenLibrary (LibName,version)(a1,d0) CloseLibrary Equ -414 ;CloseLibrary (Library)(a1) Forbid Equ -132 ;Forbid ()() Permit Equ -138 ;Permit ()() AllocMem Equ -198 ;AllocMem (bytesize,requirement)(d0,d1) FreeMem Equ -210 ;FreeMem (memoryblock,bytesize)(a1,d0) FindName Equ -276 ;FindName (list,name) (a0,a1) RemLibrary Equ -402 ;RemLibrary (library)(a1) SetSignal Equ -306 ;SetSignal (newSignals,signalMask)(d0,d1) *** *** DOS Offsets: *** OutPut Equ -60 ;OutPut () Input Equ -54 ;Input () Write Equ -48 ;Write (file,buffer,length)(d1,d2,d3) *** *** I use these Macros to make things easier for me *** doit: MACRO move.l #HeadLine,d2 ;address of HeadLine to d2 bsr TextOutPut ;output HeadLine move.l \1,d0 ;offset of listhead to d0 bsr Showlib ;output library-list ENDM *** *** Here we go: *** move.l sp,d6 ;store stack pointer on stack move.l a0,a2 ;save cmdline address sub.w #1,d0 clr.b 0(a2,d0.w) ;make the cmdline null terminated move.l ExecBase,a6 ;Execaddress to a6 (only to be sure) move.l #DOSNAME,a1 ;Librarynamepointer to a1 moveq #0,d0 ;any version jsr OpenLibrary(a6) ;try to open DOS-Libary tst.l d0 ;is d0 = NULL? beq ErrorExit ;exit if call wasn't successfull move.l d0,DOSBase ;save DOSBasepointer move.l d0,a6 ;move DOSBasepointer to a6 jsr OutPut(a6) ;identify the initial output handle move.l d0,stdout ;save stdout move.l #Text,d2 bsr TextOutPut SkipSP: move.b (a2)+,d1 ;skip spaces beq ShowTheLibs ;if NULL-String then /* show librarys */ cmp.b #' ',d1 ;is it a Space ? beq.b SkipSP ;yes -> SkipSP cmp.b #'?',d1 ;is it '?' ? beq ShowHow ;yes -> ShowHow cmp.b #'"',d1 ;is it '"' ? bne.b 001$ ;yes -> 001$ add.l #1,a2 move.l a2,a1 002$: move.b (a1)+,d1 beq NoSuchLibrary cmp.b #'"',d1 beq.b 003$ bra.b 002$ 003$: sub.l #1,a1 move.b #0,(a1) 001$: sub.l #1,a2 ;decrement address by one move.l ExecBase,a6 ;ExecBase to a6 move.l a6,a0 ;ExecBase to a0 add.l liblist,a0 ;address of librarylist to a0 move.l a2,a1 ;address of string to a1 jsr FindName(a6) ;search for the given name tst.l d0 ;is there a library with the given name beq.b NoSuchLibrary ;no -> NoSuchLibrary move.l d0,a1 ;copy address of library to a1 move.w 32(a1),d0 ;get OpenCnt tst.w d0 ;is the OpenCnt = 0? bne.b NotZero ;no -> say that the library is still open jsr RemLibrary(a6) ;try to close the library tst.l d0 bne.b Success ;->Success move.l #FailedToRemove,d2 bsr TextOutPut bra.b CloseDOS Success: move.l #Successfull,d2 bsr TextOutPut bra.b CloseDOS NoSuchLibrary: move.l #NotFound,d2 bsr TextOutPut bra.b CloseDOS NotZero: move.l #NotAbleToClose,d2 bsr TextOutPut bra.b CloseDOS ShowTheLibs: doit liblist ;output Librarylist CloseDOS: move.l ExecBase,a6 ;ExecBase to a6 move.l DOSBase,a1 ;DOS-pointer to a1 move.l ExecBase,a6 ;Exec-pointer to a6 jsr CloseLibrary(a6) ;close DOS ErrorExit: move.l d6,sp ;restore stack pointer rts ;CLI here we go again!!!! ShowHow: move.l #HelpText,d2 bsr TextOutPut bra.b CloseDOS ***************************************************************************** * * Showlib II 11.1.87 modified on 18.10.88 * by Heiko Rath * Raiffeisenstr.10a * D-6108 Weiterstadt * WEST GERMANY (F.R.G.) * * * PURPOSE: print out Librarylist (address of Node, * type, priority, name of Node, version, revision, * opencount, negative size, positive size) * * ROUTINETYPE: subroutine * * SYNTAX: bsr Showlib (Exec-offset to librarylist)(d0) * * ENTRY CONDITIONS: needs DOSlibrary opened and stdout defined * also needs DOS-'Write' offset -48 defined. * It also needs binhex subroutine. * * RETURNS: none * * BUGS: none * * NOTE: none * * CHANGED: nothing * * USAGE: move.l LibraryListOffset,d0 * bsr Showlib * ***************************************************************************** Showlib: movem.l d0-d7/a0-a6,-(sp) ;save registers move.l ExecBase,a6 ;ExecBase to a6 jsr Forbid(a6) ;forbid taskswitching (very important, ; 'cause we are accessing Systemdata) move.l a6,a0 ;Execpointer to a0 add.l d0,a0 ; + librarylistoffset=address of listhead move.l a0,ListHead ;save address of listheader -=> ListHead move.l (a0),a1 ;get address of 1.Node to a1 move.l a1,Node ;save address of 1.Node -=> Node addq.l #4,a0 cmp.l a1,a0 ;list empty? ;(test if listhead points to listhead+4) beq PrintLF ;yes -=> send LF and exit moveq.l #1,d1 ;set counter to 1 'cause there is at least ; one node in the list MyCountLoop: move.l (a1),a1 ;get address of next node to a1 tst.l (a1) ;see if contents of (a1) is NULL beq.b EndCount ;leave counting loop addq.l #1,d1 ;increment counter by one bra.b MyCountLoop ;do this once more EndCount: move.l d1,NodeCount ;save number of Nodes move.l #71,d0 ;number of bytes per node mulu d1,d0 ;bytes per node * NodeCount addq.l #1,d0 ;add one for the bufferterminating Null move.l d0,MyMemoryLength ;save lenght of Memoryblock move.l #$10001,d1 ;requirements:MEMF_Public & Clear jsr AllocMem(a6) ;get memory from system move.l d0,MyMemoryBlock ;save address of Memoryblock move.l d0,MyMemoryOffset ;save address of Memoryblock 2.time tst.l d0 ;see if call was successfull bne MoveNodeToBuffer ;yes -=> MoveNodeToBuffer move.l #Err,d2 ;this code is only here, to inform the bsr TextOutPut ; user that the AllocMem call wasn't bra PrintLF ; successfull MoveNodeToBuffer: move.l d0,a0 ;get address of MemoryBlock to a0 move.l MyMemoryLength,d1 ;get length to d1 fill: move.b #' ',(a0)+ ;fill MyMemoryBlock with spaces dbeq.b d1,fill ;is d1=NULL? (no-=>d1=d1-1-=>fill) TheLoop: move.l MyMemoryOffset,a0 ;get address of MyMemoryOffset to a0 move.l Node,a1 ;get address of current node to a1 add.l #10,a1 ;address of namepointer to a1 move.l (a1),a1 ;get address of nodename to a1 moveq.l #0,d1 ;this is faster than clr.l d1 moveq.l #0,d2 ;set this to NULL for strlen strlen: cmp.b (a1)+,d2 ;NULL? beq.b strlentest ;yes -=>strlentest addq.l #1,d1 ;increment d1 by one (stringlength) bra.b strlen ;do the loop once more strlentest: cmp.b #20,d1 ;see if string is greater #20 ble.b DoCopy ;no (less or equal)-=>DoCopy move.l #20,d1 ;set max.length to 20 DoCopy: move.l Node,a1 ;get address of node to a1 add.l #10,a1 ;address of namepointer to a1 move.l (a1),a1 ;get address of nodename to a1 tst.l d1 ;see if d1=0 bne DoTheCopy ;jump only if d1<>0 move.l #NoName,a1 ;get address of NoName to a1 moveq.l #7,d1 ;set length to 7 (length of 'No Name') DoTheCopy: subq.l #1,d1 ;decrement d1 by 1 CopyLoop: move.b 0(a1,d1),0(a0,d1) ;copy source to destination dbf d1,CopyLoop ;decrement d1, if d1<0 then out of loop move.l MyMemoryOffset,a0 ;get address of MyMemoryOffset to a0 move.b #'$',21(a0) ;store '$' move.b #'$',35(a0) ;store '$' move.b #10,69(a0) ;store LF move.b #0,70(a0) ;store end of string move.l Node,a1 ;get Nodeaddress to a1 addq.l #8,a1 ;add 8 to get address of Type moveq.l #0,d0 ;clear d0 move.b (a1),d0 ;get Type to d0 move.l MyMemoryOffset,a0 add.l #31,a0 bsr bindecb ;convert to ASCII move.l Node,a1 ;get Nodeaddress to a1 add.l #9,a1 ;add 1 to get address of Priority moveq.l #0,d0 move.b (a1),d0 move.l MyMemoryOffset,a0 add.l #35,a0 bsr bindecb move.l Node,a1 ;get Nodeaddress to a1 add.l #32,a1 ;add 32 to get address of OpenCnt moveq.l #0,d0 ;clear d0 move.w (a1),d0 ;get OpenCnt to d0 move.l MyMemoryOffset,a0 add.l #39,a0 bsr bindecw ;convert OpenCnt to ASCII move.l Node,a1 ;get Nodeaddress to a1 add.l #20,a1 moveq.l #0,d0 move.w (a1),d0 ;Version move.l MyMemoryOffset,a0 add.l #45,a0 bsr bindecw move.l Node,a1 add.l #22,a1 moveq.l #0,d0 move.w (a1),d0 ;Revision move.l MyMemoryOffset,a0 add.l #51,a0 bsr bindecw move.l Node,a1 add.l #16,a1 moveq.l #0,d0 move.w (a1),d0 ;NegSize move.l MyMemoryOffset,a0 add.l #57,a0 bsr bindecw move.l Node,a1 add.l #18,a1 moveq.l #0,d0 move.w (a1),d0 ;PosSize move.l MyMemoryOffset,a0 add.l #63,a0 bsr bindecw move.l Node,d0 ;get Nodeaddress to d2 move.l MyMemoryOffset,a0 ;get address of MyMemoryOffset to a0 add.l #22,a0 ;add 22 to get storeaddress bsr binhex ;convert address to ASCII add.l #71,MyMemoryOffset ;do this for the next loop move.l Node,a1 ;get nodeaddress to a1 move.l (a1),Node ;save address of next node move.l MyMemoryOffset,d0 ;get MyMemoryOffset to d0 addq.l #1,d0 move.l MyMemoryBlock,d1 ;get MyMemoryBlock to d1 add.l MyMemoryLength,d1 ;add MyMemoryLength to d1 cmp.l d0,d1 ;see if we have to loop once more bne TheLoop ;if <> -=> TheLoop move.l MyMemoryBlock,a0 ;get address of MyMemoryBlock to a0 add.l MyMemoryLength,a0 ;add length to MyMemoryBlock subq.l #1,a0 ;decrement address by one move.b #0,(a0) ;set last byte of MyMemoryBlock to NULL move.l NodeCount,d3 ;get number of nodes to d3 move.l MyMemoryBlock,d2 ;get address of MyMemoryBlock to d2 FinallyPrintIt: bsr TextOutPut ;print one line add.l #71,d2 ;increment string startaddress by 71 clr.l d0 ;clear newSignals clr.l d1 ;clear signalMask jsr SetSignal(a6) ;get the signalmask of our task btst #12,d0 ;is the CTRL-C Bit set? bne CTRL_C_Break ;if yes -> CTRL_C_Break tst.l d3 ;get desired flag to CCR dbeq d3,FinallyPrintIt ;is d3=NULL? (no-=>d3=d3-1-=>FinallyPrintIt move.l MyMemoryBlock,a1 ;get address of MyMemoryBlock to a1 move.l MyMemoryLength,d0 ;get length of MyMemoryBlock to d0 jsr FreeMem(a6) ;free the allocated RAM PrintLF: move.l #LF,d2 ;get address of LF-string to d2 bsr.b TextOutPut ;and get it out via DOS-Write & stdout jsr Permit(a6) ;permit taskswitching (I think Dos enables ; this for you, but I do this to be sure ; that taskswitching is now allowed.) movem.l (sp)+,d0-d7/a0-a6 ;restore Registers rts ***************************************************************************** * * TextOutPut * by Heiko Rath * Raiffeisenstr.10a * D-6108 Weiterstadt * WEST GERMANY (F.R.G.) * * PURPOSE: output a NULL-terminated string via stdout * * ROUTINE TYPE: subroutine * * SYNTAX: bsr TextOutPut (stringaddress)(d0) * * ENTRY CONDITIONS: needs DOSlibrary opened and stdout defined * also needs DOS-'Write' offset -48 defined. * * RETURNS: none * * NOTE: its better if the string is really NULL-terminated * * CHANGED: nothing * * USAGE: move.l #Textaddress,d2 * bsr TextOutPut * ***************************************************************************** TextOutPut: movem.l d0-d7/a0-a6,-(sp) ;save registers move.l d2,a0 ;address to a0 clr.l d3 ;count = 0 CountLoop: tst.b (a0)+ ;is it NULL ? beq.b PMsg ;yes: -=> determine length addq.l #1,d3 ;count = count+1 bra.b CountLoop ;test next byte PMsg: move.l stdout,d1 ;get stdout to d1 move.l DOSBase,a6 ;move DOSBase to a6 jsr Write(a6) ;write the Text movem.l (sp)+,d0-d7/a0-a6 ;reserve registers rts *********************************************************************** * * binhex * by Heiko Rath * * PURPOSE: Convert a binary value in a register to * a hex ASCII string at the destination address * * ROUTINE TYPE: SUBROUTINE * * SYNTAX: bsr binhex (source(long),destination) (d0.l,a0) * bsr binhexw (source(word),destination) (d0.w,a0) * bsr binhexb (source(byte),destination) (d0.b,a0) * * ENTRY CONDITIONS: None * * RETURNS: ASCII string in destination address * NOTE: the destination place must contain 8 bytes for any * length (byte, word, longword) * * CHANGED: Nothing * * USAGE: * * move #label,d0 * move.l address,a0 ;converts the address at label to * bsr binhex ;string at address * * move label,d0 * move.l address,a0 * bsr binhex ;conv contents at label * * move #value,d0 * move.l address,a0 * bsr binhex ;convert immediate value * **************************************************************** binhex: movem.l d0-d2/a0,-(sp) ;save registers move.l #7,d2 ;get number of counts to d2 clr.l d1 ;clear work register 001$: rol.l #4,d0 ;move high nibble to low order move.b d0,d1 ;get low order byte to d1 andi.b #$f,d1 ;isolate low order nibble cmp.b #$0a,d1 ;is it a letter or a digit? blt.b 002$ ;if digit -=> 002$ add.b #'A'-'0'-$0A,d1 ;offset for letters 002$: add.b #'0',d1 ;convert to ASCII move.b d1,(a0)+ ;store it and increment storeaddress dbf.b d2,001$ ;do the converting 8 times movem.l (sp)+,d0-d2/a0 ;restore registers rts *********************************************************************** * * bindec * by Heiko Rath * * PURPOSE: Convert a binary value in a register to * a dec ASCII string at the destination address * * ROUTINE TYPE: SUBROUTINE * * SYNTAX: * bsr bindecw (source(word),destination) (d0.w,a0) * bsr bindecb (source(byte),destination) (d0.b,a0) * * ENTRY CONDITIONS: None * * RETURNS: ASCII string in destination address * NOTE: the destination place must contain 5 bytes for any * length (byte, word). Don't use longwords! * * CHANGED: Nothing * * USAGE: * * move #label,d0 * move.l address,a0 ;converts the address at label to * bsr bindec ;string at address * * move label,d0 * move.l address,a0 * bsr bindec ;conv contents at label * * move #value,d0 * move.l address,a0 * bsr bindec ;convert immediate value * **************************************************************** bindecb: movem.l d0-d2/a0,-(sp) ;store registers move.l d0,d1 move.l a0,a1 bra.b ByteToDec bindecw: movem.l d0-d2/a0,-(sp) ;save registers move.l d0,d1 move.l a0,a1 divu #10000,d1 bsr.b StoreOneByte divu #1000,d1 bsr.b StoreOneByte ByteToDec: divu #100,d1 bsr.b StoreOneByte divu #10,d1 bsr.b StoreOneByte bsr.b StoreOneByte 003$: ;003$ is used to clear the move.b (a1)+,d0 ; leading zeros cmp.b #'0',d0 bne.b 002$ cmp.b #' ',(a1) beq.b 002$ move.b #' ',-(a1) add.l #1,a1 bra.b 003$ 002$: movem.l (sp)+,d0-d2/a0 ;restore registers rts StoreOneByte: add.b #$30,d1 move.b d1,(a0)+ clr.w d1 swap d1 rts CTRL_C_Break: move.l MyMemoryBlock,a1 ;get address of MyMemoryBlock to a1 move.l MyMemoryLength,d0 ;get length of MyMemoryBlock to d0 jsr FreeMem(a6) ;free the allocated RAM move.b #1,BreakFlag ;set our internal break flag move.l #BREAK,d2 ;get address of Break-string to d2 bsr TextOutPut ;and get it out via DOS-Write & stdout jsr Permit(a6) ;permit taskswitching (I think Dos enables ; this for you, but I do this to be sure ; that taskswitching is now allowed.) movem.l (sp)+,d0-d7/a0-a6 ;restore Registers rts *** *** Variables: *** DOSBase: dc.l 0 ;this contains the DOSlibraryaddress stdout: dc.l 0 ;this contains stdout stdin: dc.l 0 ;this contains stdin ListHead: dc.l 0 ;At runtime this contains the ; address of the listheader Node: dc.l 0 ;At runtime this contains the ; address of the current node NodeCount: dc.l 0 ;At runtime this contains the ; number of nodes in the list MyMemoryLength: dc.l 0 ;At runtime this contains the ; length of the memoryblock MyMemoryBlock: dc.l 0 ;At runtime this contains the ; address of the memoryblock MyMemoryOffset: dc.l 0 ;At runtime this contains the ; address of the memoryblock ; + 71 Bytes per finished node BreakFlag: dc.b 0 ;This is set if we encounter a CTRL-C cnop 0,2 *** ***Constants: *** liblist: dc.l $17a DOSNAME: cstring 'dos.library' cnop 0,2 Err: dc.b '*** Out of Memory Error ***',0 cnop 0,2 NoName: dc.b 'No Name',0 cnop 0,2 LF: dc.b 10,0 ;LF cnop 0,2 BREAK: dc.b '***BREAK',10,0 cnop 0,2 HeadLine: dc.b $9b,'4;32;40m' dc.b 'Name Address Typ Pri OpenC' dc.b ' Vers. Revs. Neg. Pos.' dc.b $9b,'0;31;40m',10,0 cnop 0,2 Text: dc.b $9b,'0;33;40m','Lib-Remover',$9b,'0;31;40m ' dc.b $9b,'3;31;40m','V' Version dc.b $9b,'0;31;40m' dc.b ' by ',$9b,'0;32;40m','Heiko Rath',$9b,'0;31;40m',' - ' dc.b $9b,'4;31;40m',169,'1988 by ',$9b,'1;31;40m' dc.b 'The Software Brewery',$9b,'0;31;40m',10 dc.b 'Raiffeisenstr.10a, D-6108 Weiterstadt, ' dc.b 'WEST GERMANY (F.R.G.)',10,0 Successfull: dc.b 10,'Succeeded in removing the library.',10,0 cnop 0,2 NotAbleToClose: dc.b 10,$9b,'0;33;40m','Attention:',$9b,'0;31;40m' dc.b ' This library can not be closed, cause OpenCnt > 0.',10,0 cnop 0,2 FailedToRemove: dc.b 10,$9b,'0;33;40m','Attention:',$9b,'0;31;40m' dc.b ' Failed to remove the library.',10,0 cnop 0,2 NotFound: dc.b 10,$9b,'0;33;40m','Attention:',$9b,'0;31;40m' dc.b ' Library not found.',10,0 cnop 0,2 HelpText: dc.b 10,'Use ',$9b,'0;33;40m','Remlib',$9b,'0;31;40m' dc.b ' without argument to display all libraries.',10 dc.b 'Use ',$9b,'0;33;40m','Remlib',$9b,'0;31;40m' dc.b ' "name.library" to remove a library.',10 dc.b 'Note: It''s only possible to remove libraries with',10 dc.b ' an opencount of 0.',10,0