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>