Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-05 - decus/20-0151/opset.mac
There is 1 other file named opset.mac in the archive. Click here to see a list.
	.OPVER=0		;assemble code for OPRESET
;	.OPVER=1		;assemble code for OPTEST
;	.OPVER=2		;assemble code for OPSET

	IFE .OPVER,<TITLE	OPRESET	Resets a SETUP option flag
		    IF1 <PRINTX		Assembling OPRESET code>>

	IFE .OPVER-1,<TITLE	OPTEST	Tests a SETUP option flag
		      IF1 <PRINTX	Assembling OPTEST code>>

	IFE .OPVER-2,<TITLE	OPSET	Sets a SETUP option flag
		      IF1 <PRINTX	Assembling OPSET code>>

	SEARCH MONSYM,MACSYM

	Comment	^

	Revision History

[1]	R. Swick 30-Oct-79. Initial release.

	^

	MAXCHR==^D500		;MAXIMUM # OF CHAR IN MCF LINE
	PDLEN==100		;SIZE OF STACK
	.WRDCNT==0		;#words used in SETUP.BIN
	.VARST==1		;start of linked list for variables
	.OPTST==2		;start of linked list for options
	.EMPST==3		;start of linked list for empty blocks
	WAITIM==^D10		;milliseconds between waits for access
	MAXTRY==^D200		;max # of trys to get access to list
	BINMAX==2		;max # of pages in SETUP.BIN

	SALL
F==0			;flags
	F%VAC==1B3		;access granted to variable list in SETUP.BIN
	F%OAC==1B4		;access granted to option list in SETUP.BIN
	F%EAC==1B5		;access granted to empty block list in SETUP.BIN
.AC4=4				;another temporary accumulator
T1==5
P1==10				;ACCUMULATORS USED MAINLY TO HOLD BYTE pointer
CH==15				;HOLDS A CHARACTER

	DEFINE	PARSE(typ,flgs,data,hlpm,def,lst)<
		MOVEI	.AC1,CMBLOK
		MOVEI	.AC2,[FLDDB. <typ>,<flgs>,<data>,<hlpm>,<def>,<lst>]
		COMND
		TDNE	.AC1,[CM%NOP]>

	DEFINE ITEM(text,addr)<
		XWD	[ASCIZ /text/],addr>


	DEFSTR	(VALLEN,,^D5,^D6)	;data structure for # words in value
	DEFSTR	(VALLOC,,^D17,^D12)	;data structure for addr of value
	DEFSTR	(FWDPTR,,^D35,^D18)	;data structure for linked list pntr
		SUBTTL ***MAIN PROGRAM***
START:	MOVE	P,[XWD PDLEN,PDLIST] ;initialize stack
	MOVE	.AC1,[XWD .PRIIN,.PRIOU]
	MOVEM	.AC1,CMBLOK+.CMIOJ ;setup COMND jfns
	HRROI	.AC1,[0]	;no prompt for now
	MOVEM	.AC1,CMBLOK+.CMRTY
	HRROI	.AC1,LINE
	MOVEM	.AC1,CMBLOK+.CMBFP ;COMND buffer pointer
	MOVEM	.AC1,CMBLOK+.CMPTR ;next input to be parsed
	MOVEI	.AC1,MAXCHR
	MOVEM	.AC1,CMBLOK+.CMCNT ;size of input buffer
	SETZM	BINJFN		;reset jfn of default file
	SETZ	.AC1,		;make EXEC command line available
	RSCAN%
	  NOP
	SETZ	F,		;clear all flags
	PARSE	.CMINI		;initialize COMND
	  JFCL
REPARS:	PARSE	.CMFLD		;parse the command name
	  JRST	INIERR		;couldn't parse this
	MOVE	P1,[POINT 7,ANSW1] ;assemble name here
	SETZM	ATMBUF		;initialize in case of un-parseable name
	CALL	PRSOPT		;parse an option name, leave it in ANSW1
	  JRST	INVNAM		;invalid option name
	PARSE	.CMCFM		;confirm it
	  JRST	INICFM		;not confirmed
	MOVE	.AC1,[-1,,.OPTST] ;get write access to option list
	CALL	ACCESS
	SETZM	SVALUE		;default option value to NO
	MOVEI	.AC1,.OPTST	;get option list pointer
	MOVE	.AC2,[POINT 7,ANSW1] ;find this name in list
	MOVEI	.AC3,BINDEF	;start here
	CALL	SRCHLL		;find name in list
	IFE .OPVER,<
		  SKIPA		;skip if not already there
		CALL	SELSAV	;set value to NO
		TMSG	([)
		HRROI	.AC1,ANSW1
		PSOUT%
		TMSG	( reset])>
	IFE .OPVER-1,<
		  SKIPA		;skip if not already there
		JRST	[MOVE	.AC1,LSTPTR ;else get list pointer
			 LOAD	.AC1,VALLOC,BINDEF(.AC1) ;and get value
			 SKIPN	.AC1 ;skip if set
			 JRST	.+1 ;else say not set
			 TMSG	(?)
			 HRROI	.AC1,ANSW1
			 PSOUT%
			 TMSG	( is set)
			 JRST	QUIT]
		TMSG	([)
		HRROI	.AC1,ANSW1
		PSOUT%
		TMSG	( is not set])>
	IFE .OPVER-2,<
		  CALL	SELSAV		;not there, so save it now
		MOVE	.AC1,LSTPTR
		LOAD	.AC1,VALLOC,BINDEF(.AC1) ;get option value
		SKIPE	.AC1		;must be NO
		JRST	[TMSG	(?)	;or say flag is already set
			 HRROI	.AC1,ANSW1
			 PSOUT%
			 TMSG	( is already set)
			 JRST	QUIT]	;and quit
		SETOM	SVALUE		;else set the option to be YES
		CALL	SELSAV		;store the new value
		TMSG	([)		;type out a message
		HRROI	.AC1,ANSW1
		PSOUT%
		TMSG	( set])>
QUIT:
	CALL	CLRACS		;clear any access to option list
	SKIPE	BINJFN		;skip if default file not mapped
	CALL	RELBIN		;release SETUP.BIN
	HALTF%			;quit
	JRST	.-1		;if continued
	SUBTTL	Save an option value in SETUP.BIN

; Called to save an option in SETUP.BIN
;
; Returns +1 always

SELSAV:
	MOVEI	.AC1,.OPTST
	MOVE	.AC2,[POINT 7,ANSW1] ;search for option in list
	MOVEI	.AC3,BINDEF
	CALL	SRCHLL
	  SKIPA			;not found, then store name
	JRST	SELSV2
	MOVE	.AC1,[-1,,.EMPST] ;get access to empty-block list
	CALL	ACCESS
	MOVE	.AC1,[POINT 7,ANSW1] ;byte pointer to option name
	SETZ	.AC2,		;count of bytes in name
	ILDB	.AC3,.AC1	;get a char
	SKIPE	.AC3		;found end of name?
	AOJA	.AC2,.-2	;nope, then loop again
	ADDI	.AC2,5		;round up+nul
	IDIVI	.AC2,5		;get # words needed
	AOS	.AC2		;plus one for header
	MOVEI	.AC1,.EMPST	;start of empty-block list
	CALL	SRCHMT		;find a place for name
	MOVEM	.AC1,.AC3	;save address
	ADDI	.AC1,BINDEF	;make it absolute
	ADD	.AC2,.AC1	;addr of last word to move
	AOJ	.AC1,		;leave room for header
	HRLI	.AC1,ANSW1	;move option name to there
	BLT	.AC1,(.AC2)
	MOVE	.AC1,LSTPTR	;addr of preceeding item
	LOAD	.AC2,FWDPTR,BINDEF(.AC1) ;get old fwd ptr
	STOR	.AC3,FWDPTR,BINDEF(.AC1) ;new one is this addr
	STOR	.AC2,FWDPTR,BINDEF(.AC3) ;this one points to next
	MOVEM	.AC3,LSTPTR	;save new list pointer to option
SELSV2:	MOVE	.AC3,LSTPTR	;addr of item in list
	MOVE	.AC4,SVALUE	;value of option
	STOR	.AC4,VALLOC,BINDEF(.AC3) ;store it
	RET
; Parse an option name since options may look like "(foo)" or "<foo>"

; Accepts:	P1 is a byte pointer to a place to put the parsed name
;
; Return+1:	No valid option name
; Return+2:	Option name is in place pointed to by P1

PRSOPT:
	PARSE	.CMFLD,CM%SDH,,<name>
	  RET			;invalid name
	SKIPN	ATMBUF		;saw a name?
	JRST	[ILDB	CH,CMBLOK+.CMPTR ;get the char COMND wasn't able to parse
		 CAIN	CH,15	;end of line?
		 RET		;yep, then return+1
		 CAIN	CH,12
		 RET
		 IDPB	CH,P1	;put it into ANSW1
		 SOS	CMBLOK+.CMINC ;decrement COMND state block for monitor
		 JRST	PRSOPT]
	MOVE	.AC1,P1
	HRROI	.AC2,ATMBUF
	SETZB	.AC3,.AC4
	SOUT			;move option name to ANSW1
PRSOP1:	SKIPN	CMBLOK+.CMINC	;any more characters input?
	JRST	PRSOP2		;nope
	ILDB	CH,CMBLOK+.CMPTR ;get char that terminated COMND
	CAIN	CH," "		;terminated by space
	JRST	PRSOP2
	CAIN	CH,15		;or end of line?
	JRST	PRSOP2
	CAIN	CH,12
	JRST	PRSOP2
	CAIE	CH,11		;or tab?
	JRST	[IDPB	CH,.AC1	;nope, then a part of the name
		 SOS	CMBLOK+.CMINC ;one less char for COMND to parse
		 JRST	PRSOP1]	;look some more
PRSOP2:	SETZ	CH,		;make name ASCIZ
	IDPB	CH,.AC1
	MOVNI	.AC1,1
	ADJBP	.AC1,CMBLOK+.CMPTR ;backup COMND pointer
	MOVEM	.AC1,CMBLOK+.CMPTR
	AOS	(P)		;give skip-return
	RET
	SUBTTL	Linked-list search routine

;	Accepts: AC1 = address of start of list
;		 AC2 = byte pointer to ASCIZ item to be found
;		 AC3 = base address of list to which all pointers are relative
;
;	Returns: +1 Item not found: LSTPTR = address of item preceeding this one in list
;
;		 +2 Item found:     LSTPTR = adress of item in list

SRCHLL:
	PUSH	P,.AC1		;save current list pointer
	ADD	.AC1,.AC3	;make pointer absolute
	LOAD	.AC1,FWDPTR,(.AC1) ;get forward pointer
	SKIPG	.AC1		;end of list reached yet?
	JRST	SRCHL3		;yep
	MOVE	T1,.AC1		;get new pointer
	ADD	T1,.AC3		;make forward pointer absolute
	HLL	T1,[POINT 7,0,35] ;make it a byte pointer to item

	MOVEM	T1,LSTPTR	;save it
	MOVEM	.AC2,ITMPTR	;save byte pointer to search value
SRCHL1:	ILDB	T1,LSTPTR	;get a char of the list item
	ILDB	CH,ITMPTR	;and one from the value
	SKIPN	CH		;end of value?
	JRST	SRCHL2		;yep
	CAMN	T1,CH		;equal so far?
	JRST	SRCHL1		;yep
	CAIL	T1,"a"		;raise lowercase to uppercase if possible
	CAILE	T1,"z"
	SKIPA
	SUBI	T1,"a"-"A"
	CAIL	CH,"a"		;here too
	CAILE	CH,"z"
	SKIPA
	SUBI	CH,"a"-"A"
	CAMN	T1,CH		;equal now?
	JRST	SRCHL1		;yep
	CAML	T1,CH		;list item still less?
	JRST	SRCHL3		;nope
	POP	P,LSTPTR	;discard prior pointer
	JRST	SRCHLL		;and try next item
SRCHL2:	SKIPN	T1		;end of list item reached also?
	JRST	[POP	P,LSTPTR ;discard old forward pointer
		 JRST	SRCHL4]
SRCHL3:	POP	P,LSTPTR	;restore old forward pointer
	RET
SRCHL4:	MOVEM	.AC1,LSTPTR	;update list pointer
	AOS	(P)		;give successful return
	RET
	SUBTTL	Search linked list of empty cells

; Find an empty block to store a new variable/option name or a variable value
;
; Accepts:	AC1=Addr of start of list
;		AC2=#words needed
;
; Returns:	AC1=Addr of block
;		AC2 preserved

SRCHMT:
	MOVEM	.AC1,.AC4	;save current pointer
	LOAD	.AC1,FWDPTR,BINDEF(.AC1) ;get the address of the next block
	SKIPG	.AC1		;end of list?
	JRST	[MOVE	.AC1,BINDEF+.WRDCNT ;yep then put it at the end
		 MOVEM	.AC2,.AC3 ;get word count
		 ADDB	.AC3,BINDEF+.WRDCNT ;compute # words in .BIN file
		 CAIL	.AC3,BINMAX*1K-1 ;has .BIN file grown too large?
		 JRST	SAVFIL	;yep, then file too large
		 IDIVI	.AC3,1K+1 ;compute # pages in .BIN file
		 CAMLE	.AC3,BINSIZ ;less than or equal to current count?
		 JRST	SRCHM1	;nope, then map another page
		 RET]
	LOAD	.AC3,VALLEN,BINDEF(.AC1) ;get length of block
	CAMLE	.AC2,.AC3	;will this answer fit here?
	JRST	SRCHMT		;nope, then try again
	CAME	.AC2,.AC3	;is there any extra left?
	JRST	[SUB	.AC3,.AC2 ;yep, then get #words remaining
		 STOR	.AC3,VALLEN,BINDEF(.AC1) ;update block length
		 ADD	.AC1,.AC3 ;and increment pointer
		 RET]
	LOAD	.AC3,FWDPTR,BINDEF(.AC1) ;get addr of next block
	STOR	.AC3,FWDPTR,BINDEF(.AC4) ;and update previous block
	RET
SRCHM1:	PUSH	P,.AC1		;save list addr
	PUSH	P,.AC2		;save word count
	MOVE	.AC1,.AC3	;get file page
	MOVEM	.AC1,BINSIZ	;save new page count
	HRL	.AC1,BINJFN	;plus jfn
	ADDI	.AC2,BINDEF/1K	;compute fork page
	TXO	.AC2,PM%RD+PM%WR ;for read and write
	SETZ	.AC3,		;map only one page
	PMAP%			;map it
	POP	P,.AC2		;restore word count
	POP	P,.AC1		;restore list addr
	RET
	SUBTTL	Get access to a linked list

; Accepts:	AC1=RH=addr of start of list, LH=0: read access, -1: write access
;
; Returns:	+1 always, access granted
; Uses:		AC1, AC2, AC3, AC4, left-half of list address as access flag

ACCESS:
	SKIPN	BINJFN		;has SETUP.BIN been mapped yet?
	CALL	ACCMAP		;nope, then map it now
	MOVEM	.AC1,.AC2	;move list addr to R2
	TLZ	.AC1,-1		;mask out left half
	CAIN	.AC1,.VARST	;access desired to variable list?
	JRST	[TXNE	F,F%VAC	;yep, then already accessing?
		 RET		;yep then do nothing
		 JRST	.+1]	;no, then continue
	CAIN	.AC1,.OPTST	;access desired to option list?
	JRST	[TXNE	F,F%OAC	;yep, then already accessing options?
		 RET		;yep then do nothing
		 JRST	.+1]	;no, then continue
	CAIN	.AC1,.EMPST	;access desired to empty-cell list?
	JRST	[TXNE	F,F%EAC	;yep, then already accessing list?
		 RET		;yep, then do nothing
		 JRST	.+1]	;no, then continue
	MOVEI	.AC1,MAXTRY
	MOVEM	.AC1,WAITRY	;set access trial count
	MOVEI	.AC1,1		;dismiss to get a whole time-slice
	DISMS%
ACCES2:	SKIPGE	BINDEF(.AC2)	;does someone already have write access?
	JRST	ACCES4		;yep
	TLNE	.AC2,-1		;read or write access?
	JRST	ACCES3		;write
	HLRZ	.AC1,BINDEF(.AC2) ;get read count
	AOJ	.AC1,		;increment it
	HRLM	.AC1,BINDEF(.AC2) ;and store again
	JRST	ACCES5
ACCES3:	HLRZ	.AC1,BINDEF(.AC2) ;get read count
	SKIPE	.AC1		;=zero?
	JRST	ACCES4		;nope, then wait 'till it is
	MOVNI	.AC1,1
	HRLM	.AC1,BINDEF(.AC2) ;set write access
	JRST	ACCES5
ACCES4:	SOSG	WAITRY		;list in use, so try again later
	JRST	ACCNGR		;cannot grant access
	MOVEI	.AC1,WAITIM	;how much later?
	DISMS%
	JRST	ACCES2		;try again!
ACCES5:	TLZ	.AC2,-1		;mask out left half of R2
	CAIN	.AC2,.VARST	;accessing variable list?
	TXO	F,F%VAC		;set flag
	CAIN	.AC2,.OPTST	;accessing option list?
	TXO	F,F%OAC		;set flag
	CAIN	.AC2,.EMPST	;accessing empty-cell list?
	TXO	F,F%EAC		;set flag
	RET
; Map SETUP.BIN for use by SRCHLL

ACCMAP:
	PUSH	P,.AC1
	MOVE	.AC1,[GJ%OLD+GJ%SHT]
	HRROI	.AC2,[ASCIZ /SETUP.BIN/]
	GTJFN%
	  JRST	[SKIPE	BINJFN	;on error skip if not set already
		 JRST	BINUNC	;cannot create SETUP.BIN
		 SETOM	BINJFN	;avoid looping here!
		 MOVE	.AC1,[GJ%SHT]
		 JRST	.-2]
	MOVE	.AC2,[OF%RD+OF%WR+OF%THW]
	OPENF%
	  JRST	BINOPN
	MOVEM	.AC1,.AC4	;save jfn here for a while
	HRLZ	.AC1,.AC1
	MOVE	.AC2,[.FHSLF,,BINDEF/1K]
	MOVE	.AC3,[PM%RD+PM%WR]
	PMAP%
	MOVEI	.AC1,.EMPST+1	;#words min in SETUP.BIN
	EXCH	.AC4,BINJFN	;jfn=>binjfn,binjfn=>4
	SKIPE	.AC4		;do we need to initialize SETUP.BIN?
	MOVEM	.AC1,BINDEF	;yep
	MOVE	.AC1,BINDEF	;get word count
	IDIVI	.AC1,1K+1	;compute page count-1
	MOVEM	.AC1,BINSIZ	;save the page count
	SKIPG	.AC1		;skip if  more than 1 page
	JRST	ACCMP1		;else done
	MOVEM	.AC1,.AC3	;move page count remaining to AC3
	MOVEI	.AC1,1		;start mapping w/page 1 now
	HRL	.AC1,BINJFN	;get file jfn
	MOVE	.AC2,[.FHSLF,,<BINDEF/1K>+1] ;map rest of pages after the first
	TXO	.AC3,PM%RD+PM%WR+PM%CNT
	PMAP%			;map the rest of the file
ACCMP1:
	POP	P,.AC1		;restore list address
	RET
	SUBTTL	Clear access to a linked list

;Accepts:	AC1=RH=addr of start of list
;
;Returns:	+1 always, access grated
;
;Uses:		AC1, AC2
;		left-half of list address as accesss flag

CLRACS:
	MOVEI	.AC1,.VARST	;clear variable list access
	TXZE	F,F%VAC		;skip if not accessing it
	CALL	CLRAC1		;clear access
	MOVEI	.AC1,.OPTST	;clear option list access
	TXZE	F,F%OAC		;skip if not accessing it
	CALL	CLRAC1		;clear access
	MOVEI	.AC1,.EMPST	;clear empty-cell list access
	TXZE	F,F%EAC		;skip if not accessing it
	CALL	CLRAC1		;clear access
	RET

CLRAC1:
	SKIPG	.AC2,BINDEF(.AC1) ;skip if read-only access
	JRST	[HRRZM	.AC2,BINDEF(.AC1) ;clear write access
		 RET]
	HLRZ	.AC2,BINDEF(.AC1) ;get read count
	SOJ	.AC2,		;decrement it
	HRLM	.AC2,BINDEF(.AC1) ;and store
	RET
RELBIN:				;un-map, close, and release SETUP.BIN
	MOVE	.AC1,BINJFN	;get jfn
	HRLI	.AC1,.FBSIZ	;modify byte count in FDB
	MOVNI	.AC2,1
	MOVE	.AC3,BINDEF	;to be word count
	CHFDB%
	HRLI	.AC1,.FBBYV	;make sure byte size is 36
	MOVE	.AC2,[77B11]
	MOVE	.AC3,[44B11]
	CHFDB%
	MOVNI	.AC1,1
	MOVE	.AC2,[.FHSLF,,BINDEF/1K]
	SKIPE	.AC3,BINSIZ	;get page count, skip if only one page
	JRST	[TXO	.AC3,PM%CNT ;else unmap all pages
		 AOJA	.AC3,.+1]
	PMAP%
	MOVE	.AC1,BINJFN
	CLOSF%			;close the file
	  NOP
	RET
	;**** ERROR TYPE OUT ROUTINES
FATAL:	TMSG	(%)
	MOVE	.AC1,T1
	PSOUT%
	JRST	QUIT

INIERR:	MOVEI	T1,[ASCIZ /Error initializing command line parse/]
	JRST	FATAL
INICFM:	MOVEI	T1,[ASCIZ /Unrecognized parameters at end of command/]
	JRST	FATAL
INVNAM:	MOVEI	T1,[ASCIZ /Invalid or missing option name/]
	JRST	FATAL
SAVFIL:	MOVEI	T1,[ASCIZ /Default value file has grown too large/]
	JRST	FATAL
ACCNGR:	MOVEI	T1,[ASCIZ /SETUP.BIN file is in use by another job/]
	JRST	FATAL
BINOPN:	MOVEI	T1,[ASCIZ /Cannot open SETUP.BIN/]
	JRST	FATAL
BINUNC:	MOVEI	T1,[ASCIZ /Unable to create SETUP.BIN/]
	JRST	FATAL
ANSW1:	BLOCK <MAXCHR/5>	;WORK AREA FOR LINE MUST BE SAME
				;  LENGTH AS LINE
	Z			;OVRFLOW TEST
ATMBUF:	BLOCK	<MAXCHR/5>	;COMND atom buffer
BINJFN:	0			;jfn of SETUP.BIN if needed
BINSIZ:	0			;page count of SETUP.BIN
ENTVEC:	JRST	START
	JRST	START		;for REENTER command
	EXP	3B2+1B11+2	;version 1(2)-3
ITMPTR:	0			;a byte pointer to item to be found
LINE:	BLOCK <MAXCHR/5>	;STORAGE FOR PROCESSING MCF LINE
	Z			;OVRFLOW TEST WORD-DO NOT MOVE
LSTPTR:	0			;a byte pointer to item in list
PDLIST:	BLOCK <PDLEN>		;PUSH-DOWN STORAGE
SVALUE:	0			;place to save default/old value
WAITRY:	0			;number of tries for list access
CMBLOK:	REPARS			;block for COMND
	BLOCK	6
	-1,,ATMBUF		;atom buffer
	MAXCHR			;size of atom buffer
	0			;no GTJFN block

	XLIST			;don't list literals
	LIT
	LIST
BINDEF=.!777+1+2K		;a place to map SETUP.BIN

	END	<3,,ENTVEC>