;*
;* BREAKOUT.ASM
;*	(C) Copyright 1989 Vidhyanath Rao. All rights reserved.
;*
;*	Based on the C version of Matt Dillon and used in his DME.
;*
;*


; USAGE:  char *breakout(ptr, pqut)
;	ptr: pointer to the string to break an argument out of
;	pqut: pointer to a char. 1 if the arguement was quoted;
;		2 if nesting error;
;		3 if malloc failed.
;   returned string MUST be free()'ed.

CSEG
_breakout:
	link	a5,#-256
; local variable:
;	-256(a5) :: char bfr[256];
	movem.l	d4-d7/a2-a3,-(sp)
; register variable:
;	d4.w	 :: UWORD ix	= 254 - (index into buffer)
;	d3.l	 :: UWORD count = count of unclosed quotes
;	d5.b	 :: char opc	= char closing quotes
;	d6.b	 :: char clc	= char opening quotes
;	d7.b	 :: char isaux	= char opening quotes
;	a2.l	 :: char *str	= pointer into the passed string
;	a3.l	 :: char *bp	= pointer into the local buffer
	move.l	8(a5),a0;str = *ptr
	move.l	(a0),a2;points to the beginning of the string
; go past the initial blanks and move the first non-blank char to d0.b
	move.l	#0,d7;clear error;
lp1:	cmp.b	#32,(a2)+
	beq	lp1
	move.b	-(a2),d0
	beq	out1; if empty, exit
; set opc, clc and isaux based on the first non-blank
	cmp.b	#'`',d0
	beq	la1
	cmp.b	#'(',d0
	bne	la2
	move.l	#'(',d5;opc := '('
	move.l	#')',d6;clc := ')'
	move.l	#1,d7;isaux := TRUE
	addq.l	#1,a2;correct the str pointer
	bra	la3
la1:	move.l	#'`',d5;opc := '`'
	move.l	#$27,d6;clc := '\''
	move.l	#1,d7;isaux := TRUE
	addq.l	#1,a2;correct the str pointer
	bra	la3
la2:	move.l	#0,d5;opc not applicable
	move.l	#' ',d6;clc := space
la3:	move.w	#254,d4;ix = 254
	move.l	#1,d3;count = 1 here becuase it doen't get bumped latter
	lea	-256(a5),a3;bp = bfr
lp4:	move.b	(a2)+,d0; test the next byte
	beq	out3; if null, exit, but check count first
	cmp.b	d5,d0; if opc
	beq	lb1; increase count
	cmp.b	d6,d0; if clc
	beq	lb2
	cmp.b	#'^',d0
	beq	lb3
	cmp.b	#'\\',d0
	beq	lb4
	cmp.b	#'$',d0
	beq	lb5
lf1:	move.b	d0,(a3)+;copy the char
	dbf	d4,lp4;loop if space left
outerr:	moveq.l	#3,d7;error return. no memory.
out1:	moveq.l	#0,d0;null pointer
	sub.l	#1,a2; make a2 at the last character read.
	bra	le1
lb3:	move.b	(a2)+,d0;convert the next char to a control char
	and.b	#$1f,d0
	bra	lf1
lb4:	move.b	(a2)+,d0;next char is literal
lf2:	bra	lf1
lb5:	move.l	_String,a0; strcpy String to bp
lp2:	move.b	(a0)+,(a3)+
	dbeq	d4,lp2; if no more space, quit
	tst.w	d4
	blt	out1
	subq.l	#1,a3
	bra	lp4;and loop
lb1:	addq.l	#1,d3; increment count
	bra	lf1; and continue
lb2:	subq.l	#1,d3
	bne	lf1;continue if nesting incomplete
; at exit, d0 = return string, isaux to *pqut
;	and a3 = ptr
out2:	clr.b	(a3);quoted exit
	move.w	#255,d0
	sub.w	d4,d0
	ext.l	d0
	move.l	d0,-(sp)
	jsr	_malloc;allocate space for the breakout string
	addq.l	#4,sp
	tst.l	d0
	beq	outerr;if no memory, quit
	move.l	d0,a0
	lea	-256(a5),a1
lp3:	move.b	(a1)+,(a0)+;strcpy bfr to return string
	bne	lp3
	tst.b	-1(a2);if the last char read was not the clc
	bne	le1;but a null,
	subq.l	#1,a2;correct a2
le1:	move.l	12(a5),a1
	move.b	d7,(a1);*pqut filled in
	move.l	8(a5),a3;correct str to point at the
	move.l	a2,(a3);new start
	movem.l	(sp)+,d4-d7/a2-a3
	unlk	a5
	rts
out3:	tst.b	d5;if the beginning was bracketed,
	beq	out2
	tst.l	d3;but the count is nonzero, something is amiss
	beq	out2
	move.l	#2,d7; bad command
	bra	out1

	public _breakout
	public _malloc
	public _String
END
