* LibList.asm
* display the names of resident libraries, along with their vital statistics.
* CLI only, only allowed parameter: "IDs" forces a second list of the
* libraries along with their IDStrings to be displayed.
* uses OS2

	NOLIST
	INCLUDE "dos/LVO.i"
	INCLUDE "exec/LVO.i"
	INCLUDE "dos/dos.i"
	INCLUDE "exec/lists.i"
	INCLUDE "exec/libraries.i"
	INCLUDE "exec/memory.i"
	INCLUDE "exec/execbase.i"
	LIST

MAXSTR: 	equ	100

	STRUCTURE LibInfo,0
	; (meine Erfindung, zur kompakten Speicherung der relevanten Daten)
	APTR	  li_next
	UWORD	  li_VecSize
	UWORD	  li_DataSize
	UWORD	  li_Version
	UWORD	  li_Revision
	UWORD	  li_Opens
	STRUCT	  li_Name,MAXSTR
	STRUCT	  li_ID,MAXSTR
	LABEL	  li_SIZEOF

;Register-Variablen:

_DOSBase:	equr a5
LibsAnchor:	equr d7
display_ids:	equr d6

;*********************************************************************

	SECTION prg,CODE

;Dos-Library öffnen:
_main:	OPENLIB DOSName(pc),36
	tst.l	d0
	beq	wrongdos
	move.l	d0,_DOSBase
; Parameter abfragen (hier, da sonst die Abfrage wegen '?' erst nach dem
; Ausdruck der 1. Liste käme - ugly)
	lea	Template(pc),a0
	move.l	a0,d1
	clr.l	-(sp)
	move.l	sp,d2
	moveq	#0,d3
	CALLDOS ReadArgs
	move.l	(sp)+,display_ids
	move.l	d0,d1
	beq	1$
	CALL	FreeArgs
	bra	2$
1$:	moveq	#0,display_ids

2$:	CALLEXEC Forbid 	;keine Änderungen während des Lesens !

	moveq	#0,LibsAnchor
	move.l	LibsAnchor,a2
	move.l	LibList+LH_HEAD(a6),a3

LibsLoop:
	tst.l	LN_SUCC(a3)
	beq	EndLibList

	move.l	#li_SIZEOF,d0
	move.l	#MEMF_CLEAR,d1
	CALL	AllocVec
	tst.l	d0
	beq	EndLibList		;Ende der Liste, weil kein Speicher
	move.l	a2,d1	;tst.l a2
	beq	3$
	move.l	d0,li_next(a2)
	bra	4$
3$:	move.l	d0,LibsAnchor
4$:	move.l	d0,a2
	lea	li_Name(a2),a0
	move.l	LN_NAME(a3),a1
	bsr	strncpy
	lea	li_ID(a2),a0
	move.l	LIB_IDSTRING(a3),a1
	move.l	a1,d0
	beq	2$
	bsr	strncpy
; '\n' am Ende von li_ID einsetzen:
	addq.w	#1,d0
	beq	1$
; "ausreichend" kurzer ID-String: was steht am Ende ?
	cmp.b	#10,-1(a0)
	beq	2$
	cmp.b	#10,-2(a0)
	beq	2$
	addq.w	#1,a0
; superlanger ID-String: wird einfach durch '\n' gekappt
1$:	move.b	#10,-(a0)

2$:	move.w	LIB_NEGSIZE(a3),li_VecSize(a2)
	move.w	LIB_POSSIZE(a3),li_DataSize(a2)
	move.w	LIB_VERSION(a3),li_Version(a2)
	move.w	LIB_REVISION(a3),li_Revision(a2)
	move.w	LIB_OPENCNT(a3),li_Opens(a2)

	move.l	LN_SUCC(a3),a3
	bra	LibsLoop

EndLibList:
	CALL	Permit
	lea	str1(pc),a0
	move.l	a0,d1
	CALLDOS PutStr

; Libraries sortieren.
; Das geschieht wie folgt: es wird jeweils die erste LibInfo-Struktur
; aus der Liste ab (LibsAnchor) entfernt und - richtig - in eine neue ab
; (a4) eingefügt.

	move.l	LibsAnchor,a4	;\
	move.l	(a4),LibsAnchor ;| ersten Knoten in neue Liste verlagern
	clr.l	li_next(a4)     ;/
SortLoop:
	tst.l	LibsAnchor
	beq	EndSort
	move.l	LibsAnchor,a3	;\
	move.l	(a3),LibsAnchor ;/ ausklinken
	move.l	a4,a2		;Vergleichszeiger
	moveq	#0,d4		;Zeiger, wo der Knoten davor steht
3$:	lea	li_Name(a3),a0
	lea	li_Name(a2),a1
1$:	cmp.b	(a0)+,(a1)+
	bne	2$
	tst.b	-1(a0)
	bne	1$
2$:	bgt	insert
	move.l	a2,d4
	move.l	li_next(a2),a2
	move.l	a2,d0	;tst.l a2
	bne	3$
insert: tst.l	d4
	beq	1$
	move.l	d4,a0
	move.l	a3,(a0)         ;Zeiger auf den Knoten
	move.l	a2,li_next(a3)  ;Zeiger im Knoten
	bra	SortLoop
1$:	move.l	a3,a4		;Zeiger auf den Knoten
	move.l	a2,li_next(a3)  ;Zeiger im Knoten
	bra	SortLoop

EndSort: move.l a4,LibsAnchor
	move.l	LibsAnchor,a2

OutputLoop1:
	move.l	a2,d0	;tst.l a2
	beq	EndLibsOut1

	move.w	li_Opens(a2),-(sp)
	move.w	li_Revision(a2),-(sp)
	move.w	li_Version(a2),-(sp)
	move.w	li_DataSize(a2),-(sp)
	move.w	li_VecSize(a2),d0
	ext.l	d0
	divu	#6,d0
	move.w	d0,-(sp)
	pea	li_Name(a2)
	move.l	sp,d2
	lea	format_string(pc),a0
	move.l	a0,d1
	CALL	VPrintf
	lea	14(sp),sp

	move.l	li_next(a2),a2
	bra	OutputLoop1

; is the IDString-List to be printed ?
EndLibsOut1:
	tst.l	display_ids
	beq	FreeMem

; display IDString-List
	lea	str3(pc),a0
	move.l	a0,d1
	CALL	PutStr

	move.l	LibsAnchor,a2

OutputLoop2:
	move.l	a2,d0	;tst.l a2
	beq	FreeMem
	tst.b	li_ID(a2)
	beq	1$
	pea	li_ID(a2)
	pea	li_Name(a2)
	move.l	sp,d2
	lea	format_string2(pc),a0
	move.l	a0,d1
	CALL	VPrintf
	addq.w	#8,sp
1$:	move.l	li_next(a2),a2
	bra	OutputLoop2

FreeMem: move.l _AbsExecBase,a6
	bra	2$
1$:	move.l	LibsAnchor,a1
	move.l	li_next(a1),LibsAnchor
	CALL	FreeVec
2$:	tst.l	LibsAnchor
	bne	1$
CloseDos:
	CLOSELIB _DOSBase
nodos:	moveq	#0,d0
	rts

;keine dos-library V36+
wrongdos:
	OPENLIB DOSName(pc),33
	tst.l	d0
	beq	nodos
	move.l	d0,_DOSBase
	CALLDOS Output
	move.l	d0,d1
	beq	CloseDos
	lea	DOSName(pc),a0
	move.l	a0,d2
	move.l	#DOS36Len,d3
	CALL	Write
	bra	CloseDos

;Stringkopie bis (max.) MAXSTR Zeichen:
strncpy: moveq	#MAXSTR-1,d0
1$:	move.b	(a1)+,(a0)+
	dbeq	d0,1$
	move.b	#0,-(a0)
	rts

;*********************************************************************

DOSName:	DOSNAME
		dc.b	" v36+ required",10
DOS36Len:	equ	*-DOSName
Template:	dc.b	"IDs/S",0
format_string:	dc.b	"%-25s  %7d  %4d    %4d    %4d  %4d",10,0
format_string2: dc.b	"%-25s ID = %s",0
str1:	dc.b	"Name                      #Vectors  Data Version Revison Opens",10
	dc.b	"==============================================================",10,0
str3:	dc.b	10,"Libraries with ID strings:",10,0

	END
