
;****************************************************************************
; CLI.asm                                 Copyright 1990 bei Dietmar Heidrich
;
; Startup-Modul für alle Assembler-Programme.  Dieses Modul ist reentrant und
; ARBEITET NUR UNTER DEM CLI.  Compress-Tab 8.
;
; Der Code ist dem im Addison-Wesley "ROM Kernel Reference Manual" ähnlich, nur
; wurden alle Fehler entfernt, und das Parsen der CLI-Parameter berücksichtigt
; nun die Konventionen des DOS, d.h. der String "a**b" ergibt den Namen "a*b".
;
; Das Assembler-Programm muß beim Label "_main" beginnen, welches durch XDEF
; global deklariert wird, und kann durch den Aufruf von "_exit" mit dem Fehler-
; code in D0 terminieren.
; Beim Aufruf vom CLI aus wird _main die Anzahl von CLI-Argumenten in D0 und
; der Zeiger auf das Feld mit den Zeigern auf die Argument-Strings in A0 über-
; geben.
; D0 und A0 werden auch auf den Stack geschoben ( 4(SP) für D0, 8(SP) für A0 ).
; Darüberhinaus können die Zeiger _DOSBase, _stdin, _stdout und _stderr benutzt
; werden.
;****************************************************************************



	CODE



	INCLUDE	"exec/types.i"
	INCLUDE	"exec/alerts.i"
	INCLUDE	"exec/tasks.i"
	INCLUDE	"libraries/dos.i"
	INCLUDE	"libraries/dosextens.i"
	INCLUDE	"lvo/exec.i"
	INCLUDE	"lvo/dos.i"



	XDEF	_exit
	XDEF	_SysBase
	XDEF	_DOSBase
	XDEF	_stdin
	XDEF	_stdout
	XDEF	_stderr



	XREF	_main



BP			EQUR	A5

_SysBase		EQU	4

MAXIMUM_ARGUMENTE	EQU	40
MAXIMUM_ARGBUFFER	EQU	256
LF			EQU	10
SPACE			EQU	' '



CALL	MACRO
	IFEQ NARG-2
	move.l	\2,a6
	ENDC
	IFLE NARG-2
	jsr	_LVO\1(a6)
	MEXIT
	ENDC
	FAIL	CALL MACRO ERROR
	ENDM



PSTRING	MACRO
	IFEQ NARG-1
	dc.b	end\@-1-*,'\1',LF
end\@
	MEXIT
	ENDC
	FAIL	PSTRING MACRO ERROR
	ENDM










;******************************************************************************
; Dieser Startup-Code läuft nur unter dem CLI.

Startup
	; Wir müssen reentrant sein.
	lea	BA(PC),BP		; Basiszeiger
	move.l	SP,HauptSP-BA(BP)	; rette SP
	movem.l	d0/a0,Register-BA(BP)
	clr.l	_DOSBase-BA(BP)
	moveq	#-1,d0
	lea	_stdin-BA(BP),a0
	move.l	d0,(a0)+
	move.l	d0,(a0)+
	move.l	d0,(a0)+

	; Hole die Adresse unserer Task.
	sub.l	a1,a1
	CALL	FindTask,_SysBase
	move.l	d0,a4			; Zeiger auf Task-Struktur merken

	; Öffne DOS.
	lea	DOSName-BA(BP),a1
	moveq	#LIBRARY_VERSION,d0
	CALL	OpenLibrary
	move.l	d0,_DOSBase-BA(BP)
	bne.s	0$
	; Fehler: DOS ist nicht offen.
	move.l	#(AG_OpenLib!AO_DOSLib),d7
	lea	AlertValue-BA(BP),a5
	CALL	Alert
	moveq	#100,d0
	bra	_exit



	; Hole den Standard-Input/Output-Handle.
0$	move.l	d0,a6			; _DOSBase
	CALL	Input
	move.l	d0,_stdin-BA(BP)
	CALL	Output
	move.l	d0,_stdout-BA(BP)
	move.l	d0,_stderr-BA(BP)

	; Finde den Kommandonamen.
	move.l	pr_CLI(a4),a0
	add.l	a0,a0			; BCPL-Zeiger-Konvertierung
	add.l	a0,a0
	move.l	cli_CommandName(a0),a0
	add.l	a0,a0			; BCPL-Zeiger-Konvertierung
	add.l	a0,a0

	; Initialisiere Zähler und Zeiger.
	move.l	#MAXIMUM_ARGBUFFER-1,d7
	moveq	#MAXIMUM_ARGUMENTE-2,d6	; Argumentzähler
	lea	Zeigerfeld,a4
	move.l	a4,a1
	lea	Stringspeicher-Zeigerfeld(a4),a3

	; Hole den Kommandonamen.
	moveq	#0,d0
	move.b	(a0)+,d0		; Stringlänge
	sub	d0,d7			; Unterlauf ?
	bcs.s	errorBufferOverflow	; ja, Fehler
	move.l	a3,(a1)+		; Zeiger auf Kommandonamen
	bra.s	1$

2$	move.b	(a0)+,(a3)+		; Kopiere Zeichen
1$	dbra	d0,2$			; bis Name zu Ende

	clr.b	(a3)+			; beende Kommandenamen
	movem.l	Register-BA(BP),d0/a0
	cmp.l	d7,d0			; Kommandozeile zu lang ?
	bhs.s	errorBufferOverflow	; ja

	; Parse die Argumente.
	moveq	#SPACE,d5		; verkürzt Code
	moveq	#'"',d3			; verkürzt Code
	bra	NaechstesArgument



ArgSchleife
	move.b	(a0)+,d4		; hole Zeichen
	cmp.b	d5,d4			; legales Zeichen (cmp #' ') ?
	bls.s	NaechstesArgument	; nein, nächstes Zeichen

	move.l	a3,a2			; Zeiger auf Argumentpuffer-Stelle merken
	cmp.b	d3,d4			; ist es doppeltes Hochkomma (cmp #'"') ?
	bne.s	1$			; nein
	bra.s	3$			; ja



	; Argument darf mit einem SPACE enden.
2$	move.b	(a0)+,d4		; hole Zeichen
	cmp.b	d5,d4			; Argument beendet (cmp #' ') ?
	bls.s	ArgEnd			; ja
1$	cmp.b	#'=',d4			; ein '=' ist nicht erlaubt
	beq.s	errorEquateUse		; wenn Fehler
	move.b	d4,(a3)+		; speichere Zeichen
	dbra	d0,2$			; Zeichen übrig ?
	bra.s	ArgEnd			; nein



	; Argument ist in doppelte Hochkommata eingefaßt.
4$	move.b	(a0)+,d4		; hole Zeichen
	cmp.b	d5,d4			; Argument beendet (cmp #' ') ?
	blo.s	errorIllegalArgEnd	; ja, Fehler

	; Endet Argument mit doppeltem Hochkomma ?
	cmp.b	d3,d4			; (cmp #'"')
	bne.s	5$			; nein
	subq	#1,d0			; Zeichen übrig ?
	blt.s	ArgEnd			; nein, alles OK
	move.b	(a0)+,d4		; ja, nächstes Zeichen
	cmp.b	d5,d4			; legales Zeichen (cmp #' ') ?
	bls.s	ArgEnd			; ja, alles OK
	bra.s	errorIllegalArgEnd	; nein, Fehler

	; Ist es ein Stern ?
5$	cmp.b	#'*',d4
	bne.s	6$			; nein, speichere Zeichen
	subq	#1,d0			; Zeichen übrig ?
	blt.s	errorIllegalArgEnd	; nein, Fehler
	move.b	(a0)+,d4		; hole Zeichen
	cmp.b	d5,d4			; Argument beendet (cmp #' ') ?
	blo.s	errorIllegalArgEnd	; ja, Fehler

6$	move.b	d4,(a3)+		; speichere Zeichen

	; Es MUß noch Zeichen geben, oder Fehler.
3$	dbra	d0,4$			; Zeichen übrig ?



errorIllegalArgEnd
	lea	TextIllegalArgEnd-BA(BP),a0
	bra.s	errorOut

errorBufferOverflow
	lea	TextBufferOverflow-BA(BP),a0
	bra.s	errorOut

errorEquateUse
	lea	TextEquateUse-BA(BP),a0
	bra.s	errorOut

errorTooManyArguments
	lea	TextTooManyArguments-BA(BP),a0

errorOut
	moveq	#0,d3
	move.b	(a0)+,d3		; Stringlänge
	move.l	a0,d2			; Stringzeiger
	move.l	_stderr-BA(BP),d1	; Filezeiger
	CALL	Write			; Fehler ausgeben, A6 enthält _DOSBase
	moveq	#10,d0			; Fehlercode
	bra.s	_exit			; und Ende



ArgEnd 
	clr.b	(a3)+			; Argumentende
	subq.l	#1,d6			; noch freie Zeiger übrig ?
	ble.s	errorTooManyArguments	; nein
	move.l	a2,(a1)+		; merke Zeiger auf Argumentstring

NaechstesArgument
	dbra	d0,ArgSchleife		; Zeichen übrig ?

	; Setze die Startwerte.
	move.l	a4,a0			; Zeiger auf Zeigerfeld
	neg	d6
	add	#MAXIMUM_ARGUMENTE-1,d6	; Zeigeranzahl
	move.l	d6,d0			; nach D0

	; Starte das Assembler-Programm.
	move.l	a0,-(SP)		; Startwerte auf den Stack
	move.l	d0,-(SP)
	jsr	_main

	; danach quittiere durch _exit...










;******************************************************************************
; Die Exit-Funktion.
; Eingabe:  D0 enthält den Rückgabe-Code.
; Ausgabe:  Keine Rückkehr.

_exit 
	; Schließe DOS.
	move.l	d0,d7			; rette Fehlercode
	move.l	HauptSP(PC),SP		; SP laden
	move.l	_DOSBase(PC),d0
	beq.s	1$			; wenn DOS nicht offen
	move.l	d0,a1
	CALL	CloseLibrary,_SysBase

	; Zurück ins DOS.
1$	move.l	d7,d0
	rts










;******************************************************************************
; Variablen.

	CNOP	0,4			; für MC68020

BA		; Basisadresse

_DOSBase	ds.l	1

_stdin		ds.l	1
_stdout		ds.l	1
_stderr		ds.l	1

HauptSP		ds.l	1

Register	ds.l	2

AlertValue	dc.l	-1

DOSName		DOSNAME

TextIllegalArgEnd	PSTRING <Illegal argument>
TextBufferOverflow	PSTRING <Argument buffer overflow>
TextEquateUse		PSTRING <Illegally used ''=''>
TextTooManyArguments	PSTRING <Too many arguments>





	BSS

	CNOP	0,4

Zeigerfeld	ds.l	MAXIMUM_ARGUMENTE
Stringspeicher	ds.b	MAXIMUM_ARGBUFFER










; Ende des Startup-Moduls

	END

