

.IIF	NDF	RSX	RSX	=	0	;Assume RT11	02 +
	.TITLE	AS1
	.ident	/X01.09/
	.ENABL	LC,GBL
	.LIST	MEB,CND
	.NLIST	BEX						;02 -
 
;
; AS
; GET AND PARSE COMMAND LINE
;
; VERSION X01
;
; DAVID G. CONROY	24-MAY-78
;
; EDIT HISTORY
; 01 17-Jul-79 MM	Allow null trailed command lines
; 02 28-Aug-79 MM	Added RT11 support
; 03 11-Sep-79 MM	Allow lowercase switches in RT11
; 04 04-Mar-80 MM	Up to date for "new" compiler -- no changes
; 05 23-Dec-80 RBD	Null command line produces error for RT-11
; 06 31-Dec-80 RBD	Error check .FETCH's. Change call in 'FATAL:'
;			for RT-11 to $MSG, to force hacked 'severe'
;			exit status on file failure. Add missing '#'
;			on .FETCH of source handler.
; 07 22-May-81 JF	Add code to prompt for command when GMCR$ fails.
; 08 29-May-81 MM/RBD	Catch null command lines
; 09 30-Jul-82 NWE	Added -S switch for ISD emission
;
 
	.GLOBL	GCML
.IIF EQ RSX	.GLOBL	XSTAT					;60
 
.IF NE	RSX							;02
	.MCALL	CALL
	.MCALL	RETURN
	.MCALL	DIR$
	.MCALL	FINIT$
	.MCALL	QIOW$						;07
	.MCALL	EXST$S						;07
.IFF								;02 +
	.MCALL	.GTLIN, .FETCH, .ENTER, .CSISPC, .LOOKUP
.ENDC								;02 -
 
;
; EQUIVALENCES
;
 
CR	=	15		;ASCII CARRIAGE RETURN
ALT	=	33		;ASCII ALTMODE
BLANK	=	40		;ASCII BLANK
DOLLAR	=	44		;ASCII DOLLAR SIGN
 
;
; LOCAL DATA
; DIAGNOSTICS
;
 
.IF EQ	RSX							;02 +
;
; Command line parsing database for AS
;
AREA:	.BLKW	5		;RT11 directive work block
SWTAB:	.BYTE	'B,1
	.WORD	BFLAG
	.BYTE	'D,1
	.WORD	DFLAG
	.BYTE	'G,1
	.WORD	GFLAG
	.BYTE	'L,1
	.WORD	LFLAG
	.BYTE	'N,0
	.WORD	NFLAG
	.byte	'S,1						;09
	.word	sflag						;09
	.WORD	0
;
OPMTR:	.WORD	OBLK
	.WORD	OFLAG
	.RAD50	/OBJ/
	.WORD	OFILE
	.WORD	MSG04

LPMTR:	.WORD	LBLK
	.WORD	LFLAG
	.RAD50	/LST/
	.WORD	LFILE
	.WORD	MSG05
;
PRM:	.ASCII	"AS> "
	.BYTE	200
OFLAG:	.BYTE	1		;Fool doopen routine
;
.ENDC								;02

.IF NE	RSX							;02
IOS:	.BLKW	2		;IO STATUS BLOCK		;07
GMCRP:	QIOW$	IO.WVB,1,1,,,,<PRM,4,44>	;PROMPT QIO DPB	;07
GMCRR:	QIOW$	IO.RVB,1,1,,IOS,,<GMCR+G.MCRB,79.> ;READ LINE	;07
PRM:	.ASCIZ	'AS>'						;07
								;07
MSG01:	.ASCIZ	'?AS-F-Usage: as [-bdgln] file [file ...]'
MSG02:	.ASCIZ	'?AS-F-Too many files!'
MSG03:	.ASCIZ	'%AS-W-Unknown switch "?" - ignored'
SWBYTE	=	MSG03+22.					;07-
.IFF								;02 +
MSG01:	.ASCIZ	'?AS-F-Usage AS OUT,LIST=SOURCE/B/D/G/L/N'
MSG02:	.ASCIZ	'?AS-F-Cannot open input file'
MSG03:	.ASCIZ	'%AS-W-Unknown switch "?" ignored'
SWBYTE	=	MSG03+22.
MSG04:	.ASCIZ	'?AS-F-Cannot open object file'
MSG05:	.ASCIZ	'?AS-F-Cannot open listing file'
MSG06:	.ASCIZ	'?AS-F-Handler fetch failure'			;06

.ENDC								;02 -
	.EVEN
 

.IF NE	RSX							;02
.SBTTL	RSX11-M style command line scan
;+
; ** GCML - GET COMMAND LINE
;
; GET A COMMAND LINE FROM MCR AND PARSE IT INTO ITS ARGUMENTS.
; THE POINTERS TO  THE ARGUMENTS ARE PUT IN  THE GLOBAL VECTOR
; 'ARGV' WITH A 0 WORD AT THE END. IF THE GMCR$ FAILS, READ COMMAND
; LINE FROM TI:.
;
; THIS ROUTINE ALSO SEARCHES FOR FLAG OPTIONS (THINGS  OF  THE
; FORM -???) AND PERFORMS THE REQUIRED ACTION; USUALLY THIS IS
; SETTING FLAG BYTES IN THE ROOT.
;
; USES:
;	ALL
;-
 
GCML:	FINIT$			;INITIALIZE THE FSR
	CLR	R3		;ASSUME IT'S A COMMAND		;07
	DIR$	#GMCR		;GET A COMMAND LINE FROM MCR
	BCC	20$		;GOT ONE

10$:	DIR$	#GMCRP		;PROMPT FOR THE LINE		;07
	DIR$	#GMCRR		;READ IT BACK			;07
	CMPB	IOS,#IE.EOF	;END OF FILE?			;07
	BNE	15$		;NO, DO IT			;07
	EXST$S	#EX$SUC		;YES, NORMAL EXIT		;07

15$:								;07
	CMP	IOS,#IS.CR	;WAS THE LINE GOOD		;07
	BNE	10$		;NO				;07
	INC	R3		;YES, NOT A COMMAND, THOUGH	;07
	TST	IOS+2		;NULL COMMAND LINE?		;08
	BEQ	135$		;GIVES "USAGE" MESSAGE		;08
								;07
20$:	MOV	#GMCR+G.MCRB,R0	;POINT AT COMMAND LINE
	MOV	R0,R1		;GET ANOTHER COPY		;.01 +
25$:	MOVB	(R1)+,R2	;GET THE BYTE
	BEQ	28$		;DONE IF NULL
	CMPB	R2,#CR		;NOPE, IS IT RETURN?
	BEQ	28$		;YES, EXIT
	CMPB	R2,#ALT		;NOPE, IS IT ESCAPE?
	BNE	25$		;IF NOT, LOOK SOME MORE
28$:	CLRB	-(R1)		;FORCE NULL TERMINATOR		;.01 -
	MOV	#ARGV,R1	;THIS IS WHERE WE SAVE ARGS

	TST	R3		;COMMAND FROM GMCR$?		;07
	BNE	40$		;IF EQ YES			;07
 
30$:	MOVB	(R0)+,R2	;SKIP OVER COMMAND NAME
	BEQ	10$		;PROMPT IF NONE			;07
	CMPB	R2,#BLANK	;
	BNE	30$		;KEEP LOOKING
 
40$:	MOVB	(R0)+,R2	;SKIP BLANKS BETWEEN ARGS.
	BEQ	130$		;CHECK FOR TRICKS		;.01
	CMPB	R2,#BLANK	;
	BEQ	40$		;
 
	CMPB	R2,#'-		;OPTIONS
	BNE	60$		;NO
50$:	MOVB	(R0)+,R2	;YES, GET OPTION CHARACTER
	BEQ	130$		;(TESTING FOR THE END)		;.01
	CMPB	R2,#BLANK	;
	BEQ	40$		;
	CALL	OPT		;PROCESS THE OPTION
	BR	50$		;GO FOR MORE
 
60$:	CLR	R3		;CLEAR QUOTED ARGUMENT FLAG
	CMPB	R2,#'"		;CHECK FOR QUOTES (BOTH KINDS)
	BEQ	70$		;
	CMPB	R2,#''		;
	BNE	80$		;
70$:	MOV	R2,R3		;SET FLAG, SAVE DELIMITER
	CMP	R1,#ARGVND	;ROOM?
	BHIS	140$		;NO
	MOV	R0,(R1)+	;SAVE ARGUMENT POINTER
	BR	90$		;
 
80$:	CMPB	R2,#'<		;THROW REDIRECTION AWAY
	BEQ	90$		;
	CMPB	R2,#'>		;
	BEQ	90$		;
 
	CMP	R1,#ARGVND	;NORMAL ARGUMENT
	BHIS	140$		;NO ROOM
	MOV	R0,(R1)		;SAVE THE POINTER
	DEC	(R1)+		;
 
90$:	MOVB	(R0)+,R2	;GATHER UP AN ARGUMENT
	BEQ	110$		;EXIT IF AT END			;.01
	TST	R3		;IN QUOTED FIELD
	BNE	100$		;BR IF YES
	CMPB	R2,#BLANK	;IF NOT, BLANK IS A DELIMITER
	BEQ	110$		;
	BR	90$		;
100$:	CMPB	R2,R3		;LOOK FOR MATCHING QUOTE
	BNE	90$		;
 
110$:	CLRB	-1(R0)		;MAKE THE ARGUMENT STRING ASCIZ
	TSTB	R2		;ARE WE DONE NOW		;.01
	BNE	40$		;
120$:	TST	R3		;CHECK FOR HANGING QUOTE
	BNE	140$		;ERROR
 
130$:	CMP	R1,#ARGV	;DID WE GET ANY ARGUMENTS
	BNE	160$		;YES
135$:								;08
	MOV	#MSG01,R5	;NO, GIVE USAGE MESSAGE
	BR	150$		;
 
140$:	MOV	#MSG02,R5	;TOO MANY ARGUMENTS
150$:	CALL	MSG		;
	SEC			;ERROR RETURN
	BR	170$		;
 
160$:	CLR	(R1)		;MARK THE END OF THE ARGV
	CLC			;
170$:	RETURN			;
 
;+
; ** OPT - PROCESS OPTIONS
;
; INPUTS:
;	R2=OPTION CHARACTER
;
; OUTPUTS:
;	R2=OPTION CHARACTER MAPPED TO UPPER CASE
;
; USES:
;	R5
;-
 
OPT:	CMPB	R2,#141		;CASE MAPPING
	BLO	10$
	CMPB	R2,#172
	BHI	10$
	SUB	#BLANK,R2
 
10$:	CMPB	R2,#'G		;-G	GLOBAL
	BNE	20$
	INCB	GFLAG
	BR	50$
 
20$:	CMPB	R2,#'B		;-B	BRANCHES
	BNE	25$
	INCB	BFLAG
	BR	50$
 
25$:	CMPB	R2,#'L		;-L	LISTING
	BNE	30$		;
	INCB	LFLAG		;
	BR	50$		;

30$:	CMPB	R2,#'N		;-N	NO OBJECT
	BNE	35$
	CLRB	NFLAG						;01
	BR	50$

35$:	CMPB	R2,#'D		;-D	DELETE SOURCE
	BNE	40$
	INCB	DFLAG
	BR	50$
 
40$:	cmpb	r2,#'S		;-S	Emit ISD records	;09+
	bne	45$
	incb	sflag
	br	50$						;09-

45$:	MOVB	R2,SWBYTE	;ILLEGAL OPTION
	MOV	#MSG03,R5
	CALL	MSG
 
50$:	RETURN
.ENDC

.IF EQ	RSX							;02 +
.SBTTL	RT11 style command line scan
;
;+
; ** GCML - Get command line
;
; Get a command line from RT11 and parse it, opening the file and
; setting switches as appropriate.  Note that, unlike the RSX version,
; the RT11 version of AS will process one file only.
;
;-

GCML:	.GTLIN	#CMDLIN,#PRM	;Prompt the operator
	TSTB	CMDLIN		;First byte null?			;05
	BEQ	5$		;If so, it's an error			;05
	.CSISPC	#CSIBLK,#DEFEXT,#CMDLIN ;and parse the files
	BCC	10$		;Branch if OK
5$:	MOV	#MSG01,R5	;Nope, say so				;05
	CALL	MSG		;to the terminal
	BR	GCML		;and try again.

10$:				;Now, do the switches
	MOV	(SP)+,R3	;R0 := number of switches
	BEQ	CKOPN		;Branch if none

20$:				;Do the next switch
	MOV	#SWTAB,R2	;R2 -> Switch table
	MOV	(SP)+,R1	;Get switch name and other junk
	BPL	30$		;Branch if no value
	TST	(SP)+		;Trash the value
30$:	BIC	#177640,R1	;R1 := switch ascii value	;03

40$:				;Look at a switch table entry
	TSTB	(R2)		;Is there another to scan?
	BEQ	60$		;Branch if no more to look at.
	CMPB	R1,(R2)+	;Have we come to the right place?
	BEQ	50$		;Branch if so
	ADD	#3,R2		;Nope, skip to the next switch entry
	BR	40$		;And try for it

50$:				;Found a switch
	MOVB	(R2)+,R1	;Get the value to set
	MOVB	R1,@(R2)+	;Set it here.
	BR	70$		;And go for the next one

60$:				;Here on an unknown switch
	MOV	#MSG03,R5	;Don't know this switch
	MOVB	R1,SWBYTE	;Remember it's name
	CALL	MSG		;And inform the cretin

70$:				;Done with this switch
	DEC	R3		;Is there another?
	BGT	20$		;Go for it, if so
.ENDC								;02 -

.IF EQ	RSX							;02 +
.SBTTL	CKOPN	Check for the right flavor of open files
;+
; CKOPN
;
;	Check that the right (number of) files have been opened.
;	If the source or intermediate files were explicitly specified,
;	force the appropriate "don't delete" switch on.  Open the
;	files in any case.
;-

CKOPN:
	MOV	@#50,R1		;Get top of free memory
	TST	(R1)+		;Hicore + 2 is first free
	.FETCH	R1,#SBLK	;Get the handler		;06
	BCC	5$		;Branch if OK			;06+
	MOV	#MSG06,R5	;Oh my. Fetch failed.
	JMP	FATAL		;Die
5$:	MOV	R0,R1		;Update our high-water mark	;06-
	.LOOKUP	#AREA,SFILE+FDB$CH,#SBLK ;Find the file
	BCC	10$		;Branch if no error
	MOV	#MSG02,R5	;Urk
	JMP	FATAL		;Die

10$:	MOV	#OPMTR,R5	;Now for the object file
	CALL	DOOPEN

	MOV	#LPMTR,R5	;And the list file
	CALL	DOOPEN		;Off we go

	RETURN			;All done

FATAL:	MOV	R0,-(SP)					;06+
	MOV	R5,R0
	CALL	$MSG		;Print the bad news
	MOV	(SP)+,R0
	MOV	#8.,XSTAT	;Exit with 'severe'		;06-
	SEC			;Force mainline to exit
	RETURN			;That's all we can do
.ENDC								;02 -

.IF EQ	RSX							;02 +
;
;+
; ** DOOPEN ** Open output files for RT11
;
; Calling sequence:
;
;	MOV	#free memory address,	R1
;	MOV	#parameter area,	R5
;	CALL	DOOPEN
; Exit to FATAL on error.  On return, R1 is updated, other registers
; are trashed.
;
; The parameter area has the following format:
;
; AREA:	.WORD	CSI data block address
; + 2	.WORD	Keep on present flag address
; + 4	.WORD	Extension
; + 6	.WORD	FDB address (has channel number)
; +10	.WORD	Error message address
;
; If the file is present, it is opened and the keep flag is incremented.
; If it is not present, a fake file name is built using the SBLK file
; name parameters.  If something goes wrong, MSG is called with the
; error text and we die.
;
DOOPEN:	MOV	(R5),R2		;R2 -> file data block
	TST	(R2)		;Device?
	BNE	10$		;Yes, there's a file there
	TST	2(R2)		;File name?
	BNE	10$		;Yes, there's a file there
	TSTB	@2(R5)		;No, flag (Need this one) set?
	BEQ	30$		;Clear, ignore this one
;
; /L (or /N not given) and no file is present, make one up.
;
	MOV	#SBLK+2,R0	;Use input file name
	MOV	#^RDK ,(R2)+	;Force to public disk
	MOV	(R0)+,(R2)+	;Do the file name
	MOV	(R0)+,(R2)+	;Both sides
	MOV	4(R5),(R2)	;Use the real extension
	MOV	(R5),R2		;Point R2 back to the device info.
10$:	INCB	@2(R5)		;Make sure the flag's on

;
; Now, fetch the device handler and open the file
;

20$:	.FETCH	R1,R2		;Get the handler		;06+
	BCC	25$		;Branch if OK
	MOV	#MSG06,R5
	JMP	27$		;Die
25$:	MOV	R0,R1		;Update high-water mark		;06-
	.ENTER	#AREA,@6(R5),R2,10(R2) ;Open the file
	BCC	30$		;Gotcha

	MOV	10(R5),R5	;Trouble in the city
27$:	MOV	#FATAL,(SP)	;How we die from here
30$:	RETURN			;Bye for now

.ENDC								;02 -
	.END
