; AllocMemory v1.0 - © 1993 F.Delacroix
; Usage: AllocMemory {CHIP|FAST|PUBLIC|CLEAR|LARGEST} [x]<Amount>

	incdir	Include:
	include	exec/exec.i
	include	exec/exec_lib.i
	include	libraries/dos_lib.i


DosBase=0
OutHandle=4
MemPort=8
ArgC=12
ArgV=16
Memory=416
VARSIZE=416+ML_SIZE+ME_SIZE


	sub.l	#VARSIZE,sp
	move.l	sp,a4
	lea	ArgV(a4),a1
	bsr	Parse
	move.l	d0,ArgC(a4)

	lea	DosName(pc),a1
	moveq.l	#0,d0
	move.l	4.w,a6
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,DosBase(a4)
	beq	FreeVars

	move.l	d0,a6
	jsr	_LVOOutput(a6)
	move.l	d0,OutHandle(a4)

	move.l	d0,d1
	lea	Welcome.MSG(pc),a2
	move.l	a2,d2
	move.l	#Welcome.LGT,d3
	jsr	_LVOWrite(a6)

	tst.l	ArgC(a4)
	beq	DisplayInfo

	move.l	4.w,a6
	lea	ArgV(a4),a5
	move.w	#1,Memory+ML_NUMENTRIES(a4)
	clr.l	Memory+ML_ME+ME_LENGTH(a4)
	clr.l	Memory+ML_ME+ME_REQS(a4)
	moveq	#0,d7
MoreArgs
	bsr	ExamArg
	addq	#4,a5
	subq.l	#1,ArgC(a4)
	bne.s	MoreArgs

	tst.l	d7
	beq	DisplayInfo

	jsr	_LVOForbid(a6)
	lea	PortName(pc),a1
	jsr	_LVOFindPort(a6)
	move.l	d0,MemPort(a4)
	bne.s	PortExists

	moveq.l	#MP_SIZE+PortName.LGT,d0
	move.l	#MEMF_PUBLIC+MEMF_CLEAR,d1
	jsr	_LVOAllocMem(a6)
	move.l	d0,a2
	tst.l	d0
	bne.s	PortCreated
	jsr	_LVOPermit(a6)
	move.l	OutHandle(a4),d1
	lea	CantCreatePort.MSG(pc),a2
	move.l	a2,d2
	move.l	#CantCreatePort.LGT,d3
	move.l	DosBase(a4),a6
	jsr	_LVOWrite(a6)
	bra	CloseDos
PortCreated
	move.b	#NT_MSGPORT,MP+LN_TYPE(a2)
	lea	MP_SIZE(a2),a1
	move.l	a1,MP+LN_NAME(a2)
	lea	PortName(pc),a0
	moveq.l	#PortName.LGT,d0
	jsr	_LVOCopyMem(a6)
	move.b	#PA_IGNORE,MP_FLAGS(a2)
	lea	MP_MSGLIST(a2),a0
	NEWLIST	a0
	move.l	a2,MemPort(a4)
	move.l	a2,a1
	jsr	_LVOAddPort(a6)
PortExists
	jsr	_LVOPermit(a6)
	lea	Memory(a4),a0
	jsr	_LVOAllocEntry(a6)
	btst	#31,d0
	beq.s	AllocationSuceeded
	move.l	OutHandle(a4),d1
	lea	AllocationFailed.MSG(pc),a2
	move.l	a2,d2
	move.l	#AllocationFailed.LGT,d3
	move.l	DosBase(a4),a6
	jsr	_LVOWrite(a6)
	bra.s	CloseDos
AllocationSuceeded
	move.l	d0,a3
	move.b	#NT_MESSAGE,ML+LN_TYPE(a3)
	move.l	MemPort(a4),a0
	move.l	a3,a1
	jsr	_LVOPutMsg(a6)
	move.l	OutHandle(a4),d1
	lea	AllocationSucceeded.MSG(pc),a2
	move.l	a2,d2
	move.l	#AllocationSucceeded.LGT,d3
	move.l	DosBase(a4),a6
	jsr	_LVOWrite(a6)
CloseDos
	move.l	DosBase(a4),a1
	move.l	4.w,a6
	jsr	_LVOCloseLibrary(a6)
FreeVars
	add.l	#VARSIZE,sp
	moveq	#0,d0
	rts

ExamArg:
	move.l	(a5),a0
	lea	CHIP.KWD(pc),a1
	bsr	strcomp
	tst.l	d0
	bne.s	NoChip
	or.l	#MEMF_CHIP,Memory+ML_ME+ME_REQS(a4)
	bra	ArgDone
NoChip	lea	FAST.KWD(pc),a1
	bsr	strcomp
	tst.l	d0
	bne.s	NoFast
	or.l	#MEMF_FAST,Memory+ML_ME+ME_REQS(a4)
	bra	ArgDone
NoFast	lea	PUBLIC.KWD(pc),a1
	bsr	strcomp
	tst.l	d0
	bne.s	NoPublic
	or.l	#MEMF_PUBLIC,Memory+ML_ME+ME_REQS(a4)
	bra	ArgDone
NoPublic
	lea	CLEAR.KWD(pc),a1
	bsr	strcomp
	tst.l	d0
	bne.s	NoClear
	or.l	#MEMF_CLEAR,Memory+ML_ME+ME_REQS(a4)
	bra	ArgDone
NoClear	lea	LARGEST.KWD(pc),a1
	bsr	strcomp
	tst.l	d0
	bne.s	NoLargest
	or.l	#MEMF_LARGEST,Memory+ML_ME+ME_REQS(a4)
	bra.s	ArgDone
NoLargest
	moveq.l	#0,d0
	move.l	d0,d3
	move.b	(a0),d3
	cmp.b	#'x',d3
	beq.s	HexaConvert
DecimalLoop
	move.b	(a0)+,d3
	beq.s	NumberEvaled
	cmp.b	#'0',d3
	bmi.s	InvalidArg
	cmp.b	#'9'+1,d3
	bpl.s	InvalidArg
	sub.b	#'0',d3
	moveq.l	#10,d1
	move.l	a0,-(sp)
	bsr	lmult
	move.l	(sp)+,a0
	add.l	d3,d0
	bra.s	DecimalLoop
HexaConvert
	addq.l	#1,a0
HexaConvertLoop
	move.b	(a0)+,d3
	beq.s	NumberEvaled
	cmp.b	#'0',d3
	bmi.s	InvalidArg
	cmp.b	#'9'+1,d3
	bpl.s	NoDigit
	sub.b	#'0',d3
	bra.s	AddIt
NoDigit	cmp.b	#'a',d3
	bmi.s	NoLow
	cmp.b	#'f'+1,d3
	bpl.s	NoLow
	sub.b	#'a'-$A,d3
	bra.s	AddIt
NoLow	cmp.b	#'A',d3
	bmi.s	InvalidArg
	cmp.b	#'F'+1,d3
	bpl.s	InvalidArg
	sub.b	#'A'-$A,d3
AddIt	lsl.l	#4,d0
	add.l	d3,d0
	bra.s	HexaConvertLoop
NumberEvaled
	add.l	d0,Memory+ML_ME+ME_LENGTH(a4)

ArgDone	moveq	#-1,d7
InvalidArg
	rts

strcomp:
	movem.l	a0-a1/d1,-(sp)
strcomploop
	move.b	(a0)+,d0
	beq.s	endofstring1
	cmp.b	#'a',d0
	bmi.s	nolower
	cmp.b	#'z'+1,d0
	bpl.s	nolower
	sub.b	#'a'-'A',d0
nolower	move.b	(a1)+,d1
	cmp.b	d0,d1
	beq.s	strcomploop
differentstrings
	moveq	#-1,d0
returnfromstrcomp
	movem.l	(sp)+,a0-a1/d1
	rts
endofstring1
	tst.b	(a1)
	bne.s	differentstrings
	moveq.l	#0,d0
	bra.s	returnfromstrcomp

DisplayInfo:
	move.l	DosBase(a4),a6
	move.l	OutHandle(a4),d1
	lea	ProgInfo.MSG(pc),a2
	move.l	a2,d2
	move.l	#ProgInfo.LGT,d3
	jsr	_LVOWrite(a6)
	bra	CloseDos

Parse:	movem.l	a2-a3,-(sp)
	move.l	a1,a3
	move.l	a3,-(sp)
	clr.b	-1(a0,d0)
	move.l	a0,a2
	lea	0(a0,d0.l),a1
.SkipEndSpaces
	cmp.b	#" ",-(a1)
	dbhi	d0,.SkipEndSpaces
	clr.b	1(a1)
.NextWord
	move.b	(a0)+,d1	; Next Character into D1
	beq.s	.EndOfString
	cmp.b	#" ",d1		; SPACE ?
	beq.s	.NextWord
	cmp.b	#9,d1		; TAB ?
	beq.s	.NextWord
	move.l	a2,(a3)+	; Store pointer to word
	cmp.b	#'"',d1		; " ?
	beq.s	.Quote
	move.b	d1,(a2)+	; Store character
.NextLetter
	move.b	(a0)+,d1
	beq.s	.EndOfString
	cmp.b	#" ",d1		; SPACE ?
	beq.s	.Unquote
	move.b	d1,(a2)+	; Store character
	bra.s	.NextLetter
.Unquote
	clr.b	(a2)+
	bra.s	.NextWord
.Quote	move.b	(a0)+,d1	; quoted string:ignore spaces
	beq.s	.EndOfString
	cmp.b	#'"',d1		; " ?
	beq.s	.Unquote
	cmp.b	#"*",d1		; * ?
	bne.s	.NextQuotedChar
	move.b	(a0)+,d1
	cmp.b	#"n",d1		; n ?
	beq.s	.NewLine
	cmp.b	#"N",d1		; N ?
	bne.s	.NoNewLine
.NewLine
	moveq	#10,d1		; LineFeed
	bra.s	.NextQuotedChar
.NoNewLine
	cmp.b	#"e",d1		; e ?
	beq.s	.Escape
	cmp.b	#"E",d1		; E ?
	bne.s	.NextQuotedChar
.Escape	moveq	#$1B,d1		; ESC
.NextQuotedChar
	move.b	d1,(a2)+
	bra.s	.Quote
.EndOfString
	clr.b	(a2)
	clr.l	(a3)
	move.l	(sp)+,d0
	sub.l	d0,a3
	move.l	a3,d0
	lsr.l	#2,d0
	movem.l	(sp)+,a2-a3
	rts

lmult:	move.l	d2,-(sp)	; d0.l=d0.l*d1.l
	move.l	d0,d2
	mulu	d1,d2
	move.l	d2,a0
	move.l	d0,d2
	swap	d2
	mulu	d1,d2
	swap	d1
	mulu	d1,d0
	add.l	d2,d0
	swap	d0
	clr.w	d0
	add.l	d0,a0
	move.l	a0,d0
	move.l	(sp)+,d2
	rts

DosName	dc.b	'dos.library',0
PortName
	dc.b	'AllocMemory Port',0
PortName.LGT=*-PortName

CHIP.KWD
	dc.b	'CHIP',0
FAST.KWD
	dc.b	'FAST',0
PUBLIC.KWD
	dc.b	'PUBLIC',0
CLEAR.KWD
	dc.b	'CLEAR',0
LARGEST.KWD
	dc.b	'LARGEST',0

Welcome.MSG
	dc.b	'AllocMemory 1.0 by F.Delacroix',10,10
Welcome.LGT=*-Welcome.MSG

ProgInfo.MSG
	dc.b	'Usage: AllocMemory {CHIP|FAST|PUBLIC|CLEAR|LARGEST} [x]<Amount>',10
	dc.b	'Where: CHIP,FAST,PUBLIC,CLEAR and LARGEST are memrory requirements,',10
	dc.b	'       Amount is the number of bytes of memory to allocate.Use the',10
	dc.b	'       x to enter it in hexadecimal.',10
	dc.b	'You can free all allocated memory by FreeMemory.',10
ProgInfo.LGT=*-ProgInfo.MSG


CantCreatePort.MSG
	dc.b	'Couldn''t create port !',10
CantCreatePort.LGT=*-CantCreatePort.MSG

AllocationFailed.MSG
	dc.b	'Memory allocation failed! (not enough memory)',10
AllocationFailed.LGT=*-AllocationFailed.MSG

AllocationSucceeded.MSG
	dc.b	'Allocation succeeded, MemList stored.',10
AllocationSucceeded.LGT=*-AllocationSucceeded.MSG

