	.Title	SEN -- Send packets
	.ident	-V1.0c-
;
;       Filenaam                SEN.MAC
;       Taal                    MACRO-11
;
;       Datum originele versie  25-Jun-87
;       Originele versie door   J.H.Hamakers
;                               Asea Brown Boveri b.v. , Nederland
;
;       Korte beschrijving:
;
;	This task will send packets to a specified task in various formats
;
;	Assembleren:
;
;           MAC SEN,SEN/-SP=SEN
;
;	Taskbuilden:
;
;	    TKB @SENTKB
;
;       ---------------------
;       W I J Z I G I N G E N
;       ---------------------
;       datum           inhoud                                  A.trail versie
;       -----           ------                                  ------  ------

	.ENABL	MCL
;
	.SBTTL	MACRO  -- Macro definitions
;
.MACRO	SHOW	MSG
	MOV	#'MSG',WRITE+Q.IOPL
	MOV	#'MSG'L,WRITE+Q.IOPL+2
	DIR$	#WRITE
.ENDM
;
	.SBTTL	EQU    -- Some equated symbols
;
LF     = 12
CR     = 15
ESC    = 33
SEMCOL = ';
KOMMA  = ',
TILUN  = 1		; TI LUN
CMDLUN = 2		; CMD LUN
MSGLUN = 3		; Errorfile lun
;
	.SBTTL	DATA   -- Some data areas
;
	.NLIST	BEX
;
;
DATBUF:	.BLKB	1024.		; Send data structure
DATEND:
DATPTR:	0			; Pointer in databuffer
;
DLM:	0			; Ascii delimitor char.
;
ERROR:	0			;
;
NUMBER:	0			; Value
;
RADADR:	.BLKB	3		; RAD50 char.
	.EVEN
;
TSKNAM:	.BLKW	2		; Taskname
;
TYPDEF:	0			; Status bit defaults
TYPE:	0			; Status bits
;
	TP.WOR	= 1		; - /WO word
	TP.BYT	= 2		; - /BY byte
	TP.ASC	= 4		; - /AS ascii
	TP.RAD	= 10		; - /RA rad50
	TP.FRM  = 17		; - Format bits
;
	TP.DEC	= 20		; - /DC decimal
	TP.OCT	= 40		; - /OC octal
	TP.RDX	= 60		; - Radix bits
;
	TP.REF	= 100		; - /SR reference packet
	TP.NOR	= 200		; - /SD Data packet
	TP.TYP	= 300		; - Type bits
;
	TP.DFT  = 242		; - Defaults /BY/OC/SD
	TP.SWI	= 377		; - Switches to save for default
;
	TP.NM	= 400		; - /NM No message
	TP.DAT	= 1000		; - /DA data switch or data available
	TP.HLP	= 2000		; - /HE or ? : Help requested
;
	TP.BLK  = 40000		; - Blockdata mode active
	TP.EXT  = 100000	; - Exit
;

	.SBTTL	MSG    -- Messages
;
MSGTAB:	MSG1,MSG1L,MSG2,MSG2L,MSG3,MSG3L,MSG4,MSG4L
	MSG5,MSG5L,MSG6,MSG6L,MSG7,MSG7L,MSG8,MSG8L
	MSG9,MSG9L,MSG10,MSG10L,MSG11,MSG11L
	MSG12,MSG12L,MSG13,MSG13L,MSG14,MSG14L
;
SX.CML	=	100000		; List commandline when error
;
SE.SYN	=	1 ! SX.CML
MSG1:	.ASCII	/SEN -- Command syntax error/
MSG1L=	.-MSG1
;
SS.SUC	=	2
MSG2:	.ASCII	/SEN -- Packet of /
MSG2B:	.ASCII	/     bytes sent to task /
MSG2T:	.ASCII	/      /
MSG2L=	.-MSG2
;
SE.VAL	=	3 ! SX.CML
MSG3:	.ASCII	/SEN -- Illegal value/
MSG3L=	.-MSG3
;
SE.TSK	=	4 ! SX.CML
MSG4:	.ASCII	/SEN -- Illegal taskname/
MSG4L=	.-MSG4
;
SE.NTS	=	5
MSG5:	.ASCII	/SEN -- No taskname specified/
MSG5L=	.-MSG5
;
SE.M26	=	6
MSG6:	.ASCII	/SEN -- More than 26. bytes/
MSG6L=	.-MSG6
;
SE.NAS	=	7 ! SX.CML
MSG7:	.ASCII	/SEN -- Not in ASCII mode/
MSG7L=	.-MSG7
;
SE.FUL	=	8. ! SX.CML
MSG8:	.ASCII	/SEN -- Data buffer full/
MSG8L=	.-MSG8
;
SE.NDA	=	9. 
MSG9:	.ASCII	/SEN -- No Data to send/
MSG9L=	.-MSG9
;
SE.SER	=	10.
MSG10:	.ASCII	/SEN -- Send error : /
MSG10B:	.ASCII	/      /
MSG10L=	.-MSG10
;
SE.SWC	=	11. ! SX.CML
MSG11:	.ASCII	/SEN -- Switch combination error/
MSG11L=	.-MSG11
;
SE.QIO	=	12.
MSG12:	.ASCII	/SEN -- Error occurded, LB:[1,2]QIOSYM.MSG read error/
MSG12L	=.-MSG12
;
SE.DSW	=	13.
MSG13:	.ASCII	/       /
MSGXT:	.BLKB	64.		; Error text
MSG13L	=.-MSG13
;
SE.GCL	=	14. ! SX.CML
MSG14:	.ASCII	/SEN -- Indirect commandfile open or read error/
MSG14L=	.-MSG14
;
MSG21:
.ASCII	~SEN -- Send packets:   >SEN task/sw1..../swn~
.ASCII	<CR><LF><LF>
.ASCII	~ /BY/OC,/DC  Send oct/dec bytes        /WO/OC,/DC Send oct/dec words~
.ASCII	<CR><LF>
.ASCII	~ /RA         Send RAD50 words          /AS        Send ascii bytes~
.ASCII	<CR><LF>
.ASCII	~ /SD         Send normal packet        /SR        Send ref. packet~
.ASCII	<CR><LF>
.ASCII	~ /HE or ?    Display HELP text         /DA:xxx    Specify data (last switch)~
.ASCII	<CR><LF>
.ASCII	~ /NM         No succes message~
.ASCII	<CR><LF><LF>
.ASCII	~             Default switches :  /BY/OC/SD~
.ASCII	<CR><LF><LF>
.ASCII	~  /          Change from command to data mode and vice versa.~
.ASCII	<CR><LF>
.ASCII	~  // or ^Z   Exit SEN~
.ASCII	<CR><LF><LF>
.ASCII	~  Data:    <bl>  = space(s) and/or Tab(s)~
.ASCII	<CR><LF>
.ASCII	~           <sep> = [ <bl> ] , or : [ <bl> ]~
.ASCII	<CR><LF>
.ASCII	~           <st>  =  " or  '  or \~
.ASCII	<CR><LF><LF>
.ASCII	~     /WO,/BY /DC :   8<sep>9<sep>10 ...~
.ASCII	<CR><LF>
.ASCII	~     /WO,/BY /OC :   10<sep>11<sep>12 ...   or   8.<sep>9.<sep>10. ...~
.ASCII	<CR><LF>
.ASCII	~     /RA         :   3_RAD50_char<sep>3_RAD50_char ...~
.ASCII	<CR><LF>
.ASCII	~                               A..Z, 0..9, $ and . ( _ and # for space )~
.ASCII	<CR><LF>
.ASCII	~     /AS         :   <st>string<st><sep><st> ...~
.ASCII	<CR><LF>
.ASCII	~                              and/or 8.<sep>10<sep>10. ...~
MSG21L=.-MSG21
;
MSG22:	.ASCII	<LF>
MSG22B:	.ASCII	/     SEN>/
MSG22L=	.-MSG22
;
MSG30:	.ASCII	/Enter ASCII data :/
MSG30L=	.-MSG30
;
MSG31:	.ASCII	/Enter RAD50  data :/
MSG31L=	.-MSG31
;
MSG32:	.ASCII	/Enter decimal bytes :/
MSG32L=	.-MSG32
;
MSG33:	.ASCII	/Enter octal bytes :/
MSG33L=	.-MSG33
;
MSG34:	.ASCII	/Enter decimal words :/
MSG34L=	.-MSG34
;
MSG35:	.ASCII	/Enter octal words :/
MSG35L=	.-MSG35
	.EVEN

	.SBTTL	DPB    -- DPB definitions
;
WRITE:	QIOW$	IO.WVB,TILUN,1,,,,<,,40>
;
GCLBLK:	GCMLB$	1,SEN,,CMDLUN
;
	.SBTTL	MSFDB -- File control block for error messages
;
MSGFDB: FDBDF$			;
	FDRC$A	FD.RAN		;
	FDOP$A	MSGLUN,10$,,FO.RD
;
10$:	MSGDVL,MSGDV,MSGDRL,MSGDR,MSGFLL,MSGFL	; Data set descr.
;
MSGDV:	.ASCII	/LB0:/		;
MSGDVL	=.-MSGDV		;
	.EVEN			;
MSGDR:	.ASCII  /[1,2]/		;
MSGDRL	=.-MSGDR		;
	.EVEN			;
MSGFL:	.ASCII  /QIOSYM.MSG/	;
MSGFLL	=.-MSGFL		;
	.EVEN			;
;
	FSRSZ$	1		; FSR size ( for prompting )

	.SBTTL	PARSE  -- Parse tables
;
	ISTAT$	STAT,KEY
;
STATE$	PSTART
TRAN$	$LAMDA		,DATA1	,MODTST			; Reject when not in
							;  blockmode
TRAN$	$LAMDA		,COMM				; Command mode
;
; Command mode
;
STATE$	COMM
TRAN$	'?		,$EXIT	,	,TP.HLP	,TYPE	; ?   :Helptext
TRAN$	'/		,SWIT0				; /...
TRAN$	$RAD50		,SWITCH	,TSKSAV			; Taskname

STATE$	SWITCH
TRAN$	'/		,SWIT1				; task/...
TRAN$	$EOS		,$EXIT				; task<EOS>

STATE$	SWIT0
TRAN$	'/		,$EXIT	,	,TP.EXT	,TYPE	; //  :Exit
TRAN$	$EOS		,$EXIT	,DATMSG	,TP.BLK	,TYPE	; /   :Enter blockmode
TRAN$	$LAMDA		,SWIT1				; /...

STATE$	SWIT1
TRAN$	!DASW		,SWITCH	,			; /BY/WO/OC/DC/AS/RA
TRAN$	"NM"		,SWITCH	,	,TP.NM	,TYPE	; /NM
TRAN$	"SD"		,SWITCH	,SWPRO4	,TP.NOR	,TYPE	; /SD
TRAN$	"SR"		,SWITCH	,SWPRO4	,TP.REF	,TYPE	; /SR
TRAN$	"DA"		,DATA	,SWPRO5	,TP.DAT	,TYPE	; /DA...
TRAN$	"HE"		,$EXIT	,	,TP.HLP	,TYPE	; /HE

STATE$	DATA
TRAN$	':		,DATA5				; /DA:...

STATE$	DATA1
TRAN$	$BLANK		,DATA1				;
TRAN$	SEMCOL		,$EXIT				; ;
TRAN$	'/		,DATA2				; /...
TRAN$	$LAMDA		,DATA5				; ...

STATE$	DATA2
TRAN$	'/		,$EXIT	,	,TP.EXT!TP.DAT	,TYPE
							; //      Exit
TRAN$	$EOS		,$EXIT	,	,TP.DAT	,TYPE	; /<EOS>  End blckmode
TRAN$	$LAMDA		,DATA3	,SWPRO6			; /...

STATE$	DATA3
TRAN$	!DASW		,DATA4				; /xx...

STATE$	DATA4
TRAN$	$BLANK		,DATA4				;
TRAN$	'/		,DATA3				; /xx/...
TRAN$	SEMCOL		,$EXIT	,SWPRO7			; /xx;
TRAN$	$EOS		,$EXIT	,SWPRO7			; /xx<EOS>

STATE$	DATA5
TRAN$	$BLANK		,DATA5				;
TRAN$	'"		,DATA6	,DLMSAV			; "...
TRAN$	''		,DATA6	,DLMSAV			; '...
TRAN$	'\		,DATA6	,DLMSAV			; \...
TRAN$	!RAD50		,DATA7	,RADSAV			; RAD50
TRAN$	$DNUMB		,DATA7	,DECSAV			; Decimal
TRAN$	$NUMBR		,DATA7	,OCTSAV			; Octal
TRAN$	$LAMDA		,$EXIT	,	,SE.VAL,ERROR	; Value error

STATE$	DATA6
TRAN$	$ANY		,DATA6	,ASCSAV			; <st>....
TRAN$	$ANY		,DATA7				; <st>....<st>

STATE$	DATA7
TRAN$	$BLANK		,DATA7				;
TRAN$	':		,DATA5				; ...:...
TRAN$	KOMMA		,DATA5				; ...,...
TRAN$	SEMCOL		,$EXIT				; ...;
TRAN$	$EOS		,$EXIT				; ...<EOS>

;
; Sub transitions .....
;
STATE$	DASW		
TRAN$	"BY"		,$EXIT	,SWPRO1	,TP.BYT	,TYPE	; /BY
TRAN$	"WO"		,$EXIT	,SWPRO1	,TP.WOR	,TYPE	; /WO
TRAN$	"OC"		,$EXIT	,SWPRO2	,TP.OCT	,TYPE	; /OC
TRAN$	"DC"		,$EXIT	,SWPRO2	,TP.DEC	,TYPE	; /DC
TRAN$	"AS"		,$EXIT	,SWPRO3	,TP.ASC	,TYPE	; /AS
TRAN$	"RA"		,$EXIT	,SWPRO3	,TP.RAD	,TYPE	; /RA
;

;
STATE$	RAD50
TRAN$	!RAD50S						;
STATE$
TRAN$	!RAD50S						;
STATE$
TRAN$	!RAD50S		,$EXIT				;
;

;
STATE$	RAD50S
TRAN$	'_		,$EXIT	,RADTS2			; 
TRAN$	'#		,$EXIT	,RADTS2			;
TRAN$	$RAD50		,$EXIT	,RADTS1			;
;

;
STATE$	END

	.SBTTL	ASCSAV -- Save ASCII char.
;
ASCSAV:
	CMPB	.PCHAR,DLM	; Test delimitor
	BEQ	10$		; Match => reject
	CLR	NUMBER		; 
	BISB	.PCHAR,NUMBER	; Save character
	CALLR	MOVDAT		; Move data
;
10$:
	CALLR	REJECT		;
;
;
;
	.SBTTL	DATMSG -- Data message
;
DATMSG:
	CALL	SWPRO5		; Set default switches
	CMPB	MSG2T,#40	; Taskname present ?
	BEQ	70$		;  No : => 70$
	MOV	#CMDLUN,WRITE+Q.IOLU
				; Change LUN
	BIT	#TP.ASC,TYPE	; Ascii ?
	BEQ	10$		;  No : => 10$
	SHOW	MSG30		; ASCII char
	BR	60$		;
10$:
	BIT	#TP.RAD,TYPE	; RAD50 ?
	BEQ	20$		;  No : => 20$
	SHOW	MSG31		; RAD50 Words
	BR	60$		;
20$:
	BIT	#TP.BYT,TYPE	; Bytes ?
	BEQ	40$		;  No : => 40$
	BIT	#TP.DEC,TYPE	; Decimal ?
	BEQ	30$		;  No : => 30$
	SHOW	MSG32		; Decimal bytes
	BR	60$		;
30$:
	SHOW	MSG33		; Octal bytes
	BR	60$		;
40$:
	BIT	#TP.DEC,TYPE	; Decimal ?
	BEQ	50$		;  No : => 50$
	SHOW	MSG34		; Decimal words
	BR	60$		;
50$:
	SHOW	MSG35		; Octal words
60$:
	MOV	#TILUN,WRITE+Q.IOLU
				; Change LUN
	RETURN			;
;
70$:
	MOV	#SE.NTS,ERROR	; No taskname
	CALLR	REJECT		;
;
;
;
	.SBTTL	DECSAV -- Save decimal number
;
DECSAV:
	BIT	#TP.DEC,TYPE	; Decimal ?
	BEQ	10$		;  No : => 10$
	MOV	.PNUMB,NUMBER	; Save word
	CALLR	MOVDAT		; Move data
;
10$:
	CALLR	REJECT		;
;
;
;
	.SBTTL	DLMSAV -- Save delimitor
;
DLMSAV:
	BIT	#TP.ASC,TYPE	; Ascii ?
	BEQ	10$		;  No : => 10$
	MOVB	.PCHAR,DLM	; Save delimitor
	RETURN			;
;
10$:
	MOV	#SE.NAS,ERROR	; Not in ascii mode
	CALLR	REJECT		;
;
;
;
	.SBTTL	FULL   -- Buffer full
;
FULL:
	MOV	#SE.FUL,ERROR	; Buffer full
	BIC	#TP.BLK,TYPE	; Not in blockmode anymore
	RETURN			;
;
;
	.SBTTL	MODTST -- Test mode
;
MODTST:
	BIT	#TP.BLK,TYPE	; Blockmode ?
	BEQ	10$		;  No : => 10$
	RETURN			;
;
10$:
	CALLR	REJECT		;
;
;
;
	.SBTTL	MOVDAT -- Move data in buffer
;
MOVDAT:
	CMP	DATPTR,#DATEND	; Full ?
	BHIS	30$		;  Yes : => 30$
	BIT	#TP.ASC!TP.BYT,TYPE
				; Bytes to move ?
	BEQ	10$		;  No : => 10$
	BIT	#177400,NUMBER	; Highbyte 0 ?
	BNE	40$		;  No : => 40$
	MOVB	NUMBER,@DATPTR  ; Insert byte
	BR	20$		;  => 20$
10$:
	MOV	NUMBER,@DATPTR  ; Insert word
	INC	DATPTR		; Update pointer
20$:
	INC	DATPTR		; Update pointer
	RETURN			;
30$:
	CALLR	FULL		; Buffer full
40$:
	CALLR	REJECT		; Value error
;
;
;
	.SBTTL	OCTSAV -- Save octal number
;
OCTSAV:
	BIT	#TP.OCT,TYPE	; Octal ?
	BEQ	10$		;  No : => 10$
	MOV	.PNUMB,NUMBER	; Save word
	CALLR	MOVDAT		; Move data
;
10$:
	CALLR	REJECT		;
;
;
;
	.SBTTL	RADCLR -- Clear RADIX50 data
;
RADCLR:
	CLR	RADADR		; Clear 
	CLRB	RADADR+2	;   pending char.
	RETURN			;
;
;
;
	.SBTTL	RADSAV -- Save RADIX50 data
;
RADSAV:
	MOV	#1,R1		; Allow "..."
	MOV	#RADADR,R0	; R0 => String
	CALL	$CAT5B		; Convert, allow spaces
	MOV	R1,NUMBER	; Save word
	CALL	RADCLR		; Clear RAD50 data
	CALLR	MOVDAT		; Move data
;
10$:
	CALL	RADCLR		; Clear data
	CALLR	REJECT		;
;
;
;
	.SBTTL	RADTS1 -- Save RADIX50 char.
;
RADTS1:
	BIT	#TP.RAD,TYPE	; Radix50 ?
	BEQ	10$		;  No : => 10$
	CMP	.PSTCN,#3.	; Test length
	BLOS	20$		;
10$:
	CALLR	RADERR		;  > 3 ? : => RADERR
20$:
	MOVB	@.PSTPT,R0	; Take char.
	DEC	.PSTCN		; Sub 1 from count
	ADD	.PSTCN,R3	; More char.
	SUB	.PSTCN,R4	;    to parse
	CALLR	RADTS3		;
;
	.SBTTL	RADTS2 -- Save RADIX50 space
;
RADTS2:
	BIT	#TP.RAD,TYPE	; Radix50 ?
	BNE	10$		;  Yes : => 10$
	CALLR	RADERR		;
;
10$:
	MOVB	#40,R0		; Char = space
;
RADTS3:
	TSTB	RADADR		; 1st char ?
	BNE	10$		;   No : => 10$
	MOVB	R0,RADADR	; Insert space
	BR	30$		;
10$:
	TSTB	RADADR+1	; 2nd char ?
	BNE	20$		;   No : => 20$
	MOVB	R0,RADADR+1	; Insert space
	BR	30$		;
20$:
	TSTB	RADADR+2	; 3rd char ?
	BNE	RADERR		;   No : => RADERR
	MOVB	R0,RADADR+2	; Insert space
30$:
	RETURN			;
;
RADERR:
	CALL	RADCLR		; Clear data
	CALLR	REJECT		; More than 3 characters

;
;
;
	.SBTTL	REJECT -- Reject transition
;
REJECT:
	ADD	#2,(SP)		; Reject
	RETURN			;
;
;
;
	.SBTTL	SWPROC -- Switch processors
;
	.SBTTL	SWPRO1 -- Switch processor BY,WO
;
SWPRO1:
	BIT	#TP.FRM,TYPE	; Format specified ?
	BNE	SWERR		;  Yes : => SWERR
	RETURN			;
;
	.SBTTL	SWPRO2 -- Switch processor OC,DC
;
SWPRO2:
	BIT	#TP.RDX!TP.ASC!TP.RAD,TYPE
				; Radix, /AS or /RA specified ?
	BNE	SWERR		;  Yes : => SWERR
	RETURN			;
;
	.SBTTL	SWPRO3 -- Switch processor AS,RA
;
SWPRO3:
	BIT	#TP.FRM!TP.RDX,TYPE
				; Radix or Format specified ?
	BNE	SWERR		;  Yes : => SWERR
	RETURN			;
;
	.SBTTL	SWPRO4 -- Switch processor SD,SR
;
SWPRO4:
	BIT	#TP.TYP,TYPE	; Type specified ?
	BNE	SWERR		;  Yes : => SWERR
	RETURN			;
;
	.SBTTL	SWPRO5 -- Switch processor Defaults
;
SWPRO5:
	BIT	#TP.SWI,TYPE	; Switches specified ?
	BNE	10$		;  Yes : => 10$
	BIS	TYPDEF,TYPE	; Take default
	BR	40$		;  => 40$
10$:
	BIT	#TP.TYP,TYPE	; Packet type defined ?
	BNE	20$		;  Yes  : => 20$
	MOV	TYPDEF,R0	; Take default
	BIC	#^C TP.TYP,R0	; Mask type bits
	BIS	R0,TYPE		; Insert packettype bits
20$:
	BIT	#TP.FRM,TYPE	; RAD50, ASCII, BYTE or WORD ?
	BNE	30$		;  Yes  : => 30$
	MOV	TYPDEF,R0	; Take default
	BIC	#^C TP.FRM,R0	; Mask format bits
	BIS	R0,TYPE		; Insert form bits 
30$:
	BIT	#TP.RDX,TYPE	; OCTAL or DECIMAL ?
	BNE	40$		;  Yes  : => 40$
	MOV	TYPDEF,R0	; Take default
	BIC	#^C TP.RDX,R0	; Mask radix bits
	BIS	R0,TYPE		; Insert radix bits 
40$:
	RETURN			;
;
	.SBTTL	SWPRO6 -- Switch processor Save defaults
;
SWPRO6:
	BIC	#^C TP.SWI,TYPE	; Clear all but switches
	MOV	TYPE,TYPDEF	; Save for default	
	CLR	TYPE		; Clear bits
	RETURN			;
;
	.SBTTL	SWPRO7 -- Switch processor change within blockmode
;
SWPRO7:
	CALL	DATMSG		; Take defaults and give message
	BR	10$		;   OK =>
	CALLR	REJECT		; 
10$:
	BIT	#TP.ASC!TP.BYT,TYPE
				; Bytes to move ?
	BNE	20$		;  Yes : => 20$
	BIT	#1,DATPTR	; Even boundary ?
	BEQ	20$		;  Yes : => 20$
	CMP	DATPTR,#DATEND	; Full ?
	BHIS	30$		;  Yes : => 30$ 
	CLRB	@DATPTR		; Clear byte
	INC	DATPTR		;
20$:
	BIS	#TP.BLK,TYPE	; Still in blockmode	
	RETURN			;
;
30$:
	CALLR	FULL		; Buffer full
;
SWERR:
	MOV	#SE.SWC,ERROR	; Switch combination error
	CALLR	REJECT
;
;
;
	.SBTTL	TSKSAV -- Save taskname
;
TSKSAV:
	CMP	.PSTCN,#6.	; Length > 6 ?
	BHI	40$		;  Yes : => 40$
	MOV	#MSG2T+6.,R1	; R1 => Message
	MOV	#6.,R2		; R2 =  Length
10$:
	MOVB	#40,-(R1)	; Blank
	SOB	R2,10$		;   string
;
	MOV	.PSTPT,R0	; R0 => String
	MOV	.PSTCN,R2	; R2 =  Length
20$:
	MOVB	(R0)+,(R1)+	; Copy
	SOB	R2,20$		;   string
;
	CLR	TSKNAM+2	; 2nd word = 0
	MOV	.PSTPT,R0	; R0 => String
	MOV	#1,R1		; Allow "..."
	CALL	$CAT5		; Convert
	MOV	R1,TSKNAM	; Taskname
	BCS	30$		; Error => 30$
	MOV	#1,R1		; Allow "..."
	CALL	$CAT5		; Convert
	MOV	R1,TSKNAM+2	; Taskname
30$:
	RETURN			;
;
40$:
	MOV	#SE.TSK,ERROR	; Tasname error
	CALLR	REJECT		;

	.SBTTL	MAIN   -- Main program
;
START:
	FINIT$			; Init FSR
	MOV	#TP.DFT,TYPDEF	; Set default
	BR	RESTR1		; =>
RESTRT:
	BIT	#TP.EXT,TYPE	; Exit ?
	BNE	EXIT		;  Yes : => EXIT
	CALL	SWPRO6		;
RESTR1:
	MOV	#DATBUF,DATPTR	; Point to start of data
BLOCK:
	BIT	#TP.EXT,TYPE	; Exit ?
	BNE	EXIT		;  Yes : => EXIT
	CLR	ERROR		; Clear pending error
	BIT	#TP.BLK,TYPE	; Blokmode ?
	BEQ	20$		;  No : => 20$
	MOV	#MSG22B,R0	; R0 => String
	MOVB	#'B,(R0)+	; Assume bytes
	MOV	DATPTR,R1	; R1 => last data
	SUB	#DATBUF,R1	; R1 =  # of bytes
	BIT	#TP.BYT!TP.ASC,TYPE
				; Ascii or bytes ?
	BNE	10$		;  Yes : => 10$
	MOVB	#'W,-1(R0)	; Words
	ASR	R1		; R1 =  # of words
10$:
	MOV	#17012,R2	; R2 =  Parameters
	CALL	$CBTA		; Convert to ASCII
;
	GCML$	#GCLBLK,#MSG22,#MSG22L
				; Get commandline
	BR	30$		; => 30$
20$:
	GCML$	#GCLBLK		; Get commandline
30$:
	BCC	PARSE		; Ok => PARSE
	CMPB	GCLBLK+G.ERR,#GE.EOF
	BEQ	EXIT		; End Of File => Exit
	MOV	#SE.GCL,ERROR	; GCL error
	CALL	ERRMSG		;
EXIT:
	EXIT$S			; Exit
PARSE:
	MOV	#1,R1		; Do not suppress blanks
	MOV	#KEY,R2		; R2 => Key table
	MOV	G.CMLD  (R0),R3	; R3 =  Length
	BEQ	BLOCK		; Empty line ? => BLOCK
	MOV	G.CMLD+2(R0),R4	; R4 => CMDLINE
	MOV	R4,R5		; R5 => CMDLINE
	ADD	R3,R5		; R5 => end of CMDLINE
	CLRB	(R5)		; Clear byte
	MOV	#STAT,R5	; R5 => State table
	CALL	.TPARS		; Parse
	MOV	ERROR,R0	; Errorcode ? ( "Mov" to save carry bit ) 
	BNE	20$		;  Yes : => 20$
	BCC	30$		; Parse OK ? => 30$
	MOV	#SE.SYN,ERROR	; Syntax error
20$:
	CALL	ERRMSG		; Give message
	BIT	#TP.BLK,TYPE	; In blockmode ?
	BNE	BLOCK		;  Yes : => BLOCK
	BR	RESTR1		; Restart
;
30$:
	BIT	#TP.HLP,TYPE	; Help ?
	BEQ	40$		;  No : => 40$
	SHOW	MSG21		; Help text
	BIC	#TP.HLP,TYPE	; Clear helpbit
	BR	RESTR1		; Restart
40$:
	BIT	#TP.DAT,TYPE	; Data present ?
	BNE	50$		;  Yes : => 50$
	JMP	BLOCK		; => BLOCK
50$:

	.SBTTL PREPRO -- Preprocessor
;
PREPRO:
;
; Calculate length of data .....
;
	MOV	#DATBUF,R2	; R2 => Databuffer
	MOV	DATPTR,R3	; R3 => Data end
	SUB	R2,R3		; R3 =  Length
	BNE	10$		;  Any data ? Yes : => 10$
	MOV	#SE.NDA,ERROR	; NO DATA
	BR	ERR		; =>
10$:
;
; SEND or VSEND .....
;
	BIT	#TP.REF,TYPE	; Reference packet ?
	BNE	REFPAC		;  Yes : => REFPAC
;
;
;
	.SBTTL	NORPAC -- Normal packets
;
	CMP	R3,#26.		; Does it fit ?
	BLOS	20$		;  Yes : => 20$
;
; Packet too long
;
	MOV	#SE.M26,ERROR	; More than 26. bytes
	BR	ERR		;
;
20$:
;
;	+++++++++++++++++++++++++
;
	SDAT$S	#TSKNAM,#DATBUF	;	SEND DATA
;
;	+++++++++++++++++++++++++
;
	BR	POSPRO		;
;
;
;
	.SBTTL	REFPAC -- Reference packets
;
REFPAC:
;
	MOV	#TSKNAM,R1	; R1 => Taskname
;
;	+++++++++++++++++++++++++
;
	CALL	$VSEND		;	SEND DATA
;
;	+++++++++++++++++++++++++
;
;
;
	.SBTTL POSPRO -- Postprocessor
;
POSPRO:
	BCC	20$		; OK => 20$
	MOV	#MSG10B,R0	; R0 => String
	MOV	$DSW,R1		; R1 =  Value
	MOV	#23412,R2	; R2 =  Parameters
	CALL	$CBTA		; Convert DSW code
	MOV	#SE.SER,ERROR	; SEND ERROR
	MOV	$DSW,-(SP)	; R1 =  Value
	CALL	ERRMSG		; Error message
;
	MOV	(SP)+,R1	; R1 =  Value
	OPEN$R	#MSGFDB,,,,,,10$
				; Open QIOSYM.MSG
	NEG	R1		; Make it positive
	ADD	#128.,R1	; Take offset to dsw - codes
	GET$R	#MSGFDB,#MSGXT,#64.,R1,#0,10$
				; Get record
	CLOSE$	#MSGFDB		; Close file
	MOV	#SE.DSW,ERROR	; 
	BR	ERR		; Error message
10$:
	MOV	#SE.QIO,ERROR	; 
	BR	ERR		;
;
20$:
	MOV	#MSG2B,R0	; R0 => String
	MOV	R3,R1		; R1 =  Bytecount
	MOV	#23012,R2	; R2 =  Parameters
	CALL	$CBTA		; Convert packet length
	MOV	#SS.SUC,ERROR	; SUCCESSFULL
	BIT	#TP.NM,TYPE	; Message ?
	BEQ	ERR		;  Yes : => ERR
	JMP	RESTRT		; Restart
ERR:
	CALL	ERRMSG		; Give message
	JMP	RESTRT		; Restart

	.SBTTL	ERRMSG -- Print error message
;
ERRMSG:
	MOVB	ERROR,R0	; R0 = ERROR
	DEC	R0		; +
	ASL	R0		;  Normalize
	ASL	R0		; -
	MOV	MSGTAB   (R0),WRITE+Q.IOPL
	MOV	MSGTAB+2(R0),WRITE+Q.IOPL+2
	DIR$	#WRITE		;
	BIT	#SX.CML,ERROR	; List commandline ?
	BEQ	10$		;  No : => 10$
	MOV	GCLBLK+G.CMLD+2,WRITE+Q.IOPL
	MOV	GCLBLK+G.CMLD  ,WRITE+Q.IOPL+2
	DIR$	#WRITE		;
10$:
	RETURN			;
;
	.END	START
