Trailing-Edge
-
PDP-10 Archives
-
tops20tools_v6_9-jan-86_dumper
-
tools/sed2/sed1ex.mar
There are 5 other files named sed1ex.mar in the archive. Click here to see a list.
.TITLE SED1EX - Sed routines for the Execute Command
.LIBRARY /SEDITB.MLB/
.ENABLE DEBUG
.DISABLE GLOBAL
.PSECT CODE,NOWRT,EXE,LONG
.NOCROSS
FLGDEF ;Define the flag bits
PRMDEF ; and the SED parameters
$IODEF ; and the I/O symbols
$XABFHCDEF ; and the fixed header XAB symbols
.CROSS
.SUBTITLE Execute Command Processor
EXECUT::BICL #M_PCM,F ;Cancel the pick-close mark, if any
BBCC #V_CMV,F,10$ ;Did user use cursor movement?
MOVAB PARBUF,R3
BSBW PELS.M ;Yes - read parameter from the file
BRB 20$
10$: CLRB @PARPTR ;End buffer with a null
20$: MOVZBL PARBUF,R1 ;Get first character of parameter
CMPB R1,#^A"a" ;Lower case?
BLSS 30$ ;No
SUBB #^O40,R1 ;Yes - convert to upper
30$: CMPB R1,#^A"S" ;Set up a buffer?
BNEQ 40$ ;No
BRW XCTSET ;Yes - do it
40$: CMPB R1,#^A"K" ;Kill a buffer?
BNEQ 50$ ;No
BRW XCTKIL ;Yes - do it
50$: CMPB R1,#^A"W" ;Write into a buffer?
BNEQ 60$ ;No
BRW XCTWRT ;Yes - do it
60$: CMPB R1,#^A"R" ;Read and list a buffer in switch format?
BNEQ 70$ ;No
BRW XCTRDL ;Yes - do it
70$: CMPB R1,#^A"L" ;Read and list a buffer in write format?
BNEQ 80$ ;No
BRW XCTRDW ;Yes - do it
80$: CMPB R1,#^A"N" ;List the defined buffer names?
BNEQ 90$ ;No
BRW XCTNML ;Yes - do it
90$: CMPB R1,#^A"X" ;Write and execute buffer?
BNEQ 100$ ;No
BRW XCTXCT ;Yes - do it
100$: CMPB R1,#^A"B" ;Link buffer to a keyboard button?
BNEQ 110$ ;No
BRW XCTBTN ;Yes - do it
110$: CMPB R1,#^A"@" ;Read a file of buffer switches?
BNEQ EXCUT0 ;No
BRW XCTBSW ;Yes - do it
;Here to set up a number of iterations
EXCUT0: BSBW PEEL.1 ;Read parameter, if any
TSTL R1 ;Any parameter?
BNEQ 10$ ;Yes
BRW EXCOPN ;No - just open execute buffer
10$: MOVL PARG1,R4 ;Else get number of iterations
MOVL R4,R3 ;Here, too
MOVL XCTITR,R0 ;Save as new nominal
MOVL R4,XCTITR
MOVL R0,R4
EXCUT1: MOVL XCTNUM,R0 ;and as current number
MOVL R3,XCTNUM
MOVL R0,R3
MOVL XCTACW,R1 ;Get buffer pointer
BGEQ 10$ ;Is there one?
BRW XCOERR ;No - no-active-buffer error
10$: MOVL XCTADR[R1],R1
BEQL 15$ ;Any address there? No
TSTB (R1) ;Make sure there's something there
BNEQ 20$
15$: BRW XCXERR ;If nothing there, error
20$: TSTB XSHFLG ;Want to display the execute?
BEQL 30$ ;No
JSB ERASPM ;Yes - erase parameter
30$: BBS #V_JRC,F1,EXCU1A ;If doing journal restore, it's top lvl xct
BITL #M_XCT!M_XBN,F1 ;Already executing?
BEQL EXCU1A ;No
BRW EXCSVX ;Yes - save context (return to EXCU1C)
EXCU1A: PUSHR #^M<R1,R2,R3,R4,R5>
MOVC3 #SAVPML,PARAMS,SAVPRM ;Save all parameters
POPR #^M<R1,R2,R3,R4,R5>
MOVL F,SAVFGS ;Save flag longword 1
MOVL F1,SAVFGS+4 ; and longword 2
BICL #M_XCT!M_XBN!M_JRC,F1 ;Clear journal-restore flags
EXCU1B: TSTB XSHFLG ;Want to display the execute?
BEQL 10$ ;No
BISL #M_XBN,F1 ;Yes - set the right flag
BRB EXCU1C
10$: BISL #M_XCT,F1 ;No - set the right flag
EXCU1C: MOVL XCTACW,R1 ;Get buffer pointer
MOVL XCTADR[R1],R1
MOVL R1,XCTACR ;Set buffer up for reading
MOVL R1,XCTPTR
BBCC #V_XSV,F1,10$ ;Saving commands?
BSBB XCTWIP ;Yes - wipe out the "enter number execute"
10$: BRW XCTEND ;Finish off
;Subroutine to wipe out the execute command ("ENTER SOMETHING EXECUTE")
;from the buffer
XCTWIP: MOVL XCTPTW,R6 ;Get pointer to end of buffer
10$: MOVZBL -(R6),R1 ;Get character
CMPB R1,#^O33 ;Enter?
BNEQ 10$ ;No - keep skipping
XCTCLO: CLRB -1(R6) ;Yes - save a null over the enter
MOVB #-1,(R6)+ ;Flag the end of the buffer
MOVL R6,XCFPTR ;Save new start-of-free-space pointer
RSB ;Done
;Here to save current buffer status so another can be executed
EXCSVX: TSTL XCTPSV ;Already down a level?
BEQL 10$
BRW XSXERR ;Yes - only one stack allowed
10$: MOVL XCTPTR,XCTPSV ;No - save active buffer pointer
MOVL XCTACR,XCTASV ; and active buffer starting pointer
MOVL R3,XCTNSV ;Save active number of iterations
MOVL R4,XCTISV ; and nominal number of iterations
BRB EXCU1C ;Finish the set-up
;Here for just enter execute: open buffer and start saving commands
EXCOPN: BISL #M_XSV,F1 ;Set flag to save commands
MOVL #1,XCTITR ;Set default number of iterations to 1
MOVL #1,XCTNUM
EXCOP1: MOVL XCTACW,R1 ;Is there an active buffer?
BGEQ 10$
BRW XCOERR ;No - error
10$: MOVL XCFPTR,R2 ;Yes - get pointer to start of free space
MOVL R2,XCTPTW ;Save as write-pointer to buffer data
MOVL R2,XCTADR[R1] ; and as stored pointer to buffer data
XCTEND: JSB ERASPM
JMP DISCUR ;Re-position cursor and loop
;Here to set up an execute buffer - if given name is not found,
;create buffer with that name
XCTSET::BBCC #V_XSV,F1,10$ ;Was a buffer open?
BSBW XCTWIP ;Yes - close it
10$: BSBW XCTRED ;Read buffer name and find it
TSTL R1 ;Found?
BGEQ 40$ ;Yes
MOVL #XBFNUM-1,R1 ;No - create it. Find an open slot
20$: MOVQ XCTNAM[R1],R2 ;Is this one open?
BEQL 30$ ;Yes
SOBGEQ R1,20$ ;No - step to the next slot
BRW XCSERR ;Jump if none open - error
30$: MOVQ XCTTMP,XCTNAM[R1] ;Save name in this slot
40$: MOVL R1,XCTACW ;Save index of active buffer
BBSC #V_FLG ,F,50$ ;Want to return (to SWHMNY)?
BRB XCTEND ;No
50$: RSB ;Yes
;Here to kill off a given execute buffer
XCTKIL: BBCC #V_XSV,F1,10$ ;Was a buffer open?
BSBW XCTWIP ;Yes - close it
10$: BSBW XCTRED ;Read and find name of buffer
TSTL R1 ;Was it found?
BGEQ 20$ ;Yes
BRW XCKERR ;Not found - error
20$: MOVL R1,R2
BSBB XCTKLL ;Else zero out its information
CMPL R2,XCTACW ;is this the active one?
BNEQ 30$
CVTBL #-1,XCTACW ;Yes - say there is no active buffer
30$: BRB XCTEND ;Done
XCTKLL: CLRQ XCTNAM[R2] ;Zero out the buffer name
BSBB XCTKLF ;Delete the buffer contents from free space
XCTKLK::MOVQ XCTKEY[R2],R0 ;Is there a key?
BEQL 10$ ;No - done
MOVAQ XCTKEY[R2],R6
CVTBL #-1,SAVEAC+24 ;Restore command in table
BSBW SUBTBX
CLRQ XCTKEY[R2] ;Clean out old key
10$: RSB
;Subroutine to kill the contents of an execute buffer from free space
;Enter with R2/ buffer index
XCTKLF: MOVL XCTADR[R2],R4 ;Get execute buffer pointer
BNEQ 10$ ;Any?
RSB ;No - nothing to kill
10$: MOVZBL (R4)+,R1 ;Get a buffer data byte
CMPB #^XFF,R1 ;Is it the last byte?
BNEQ 10$ ;No - loop until found
CLRB -1(R4) ;Turn off the end-of-data flag
MOVL XCTADR[R2],R1 ;Get pointer to start of data
CLRL XCTADR[R2] ; and clear the pointer
CMPL R4,XCFPTR ;Does this data area butt against free space?
BNEQ 20$ ;No
MOVL R1,XCFPTR ;Yes - save as new start of free space
20$: RSB ;Done
;Here to save a string into the active buffer
XCTWRT::BBCC #V_XSV,F1,10$ ;Was a buffer open?
BSBW XCTWIP ;Yes - close it
10$: MOVAB PARBUF+1,R6
XCWRT0::MOVL XCTACW,R2 ;Get pointer to old buffer contents
BGEQ 10$
BRW XCOERR ;None active - error
10$: BSBB XCTKLF ;Delete previous contents from free space
MOVL XCFPTR,R4 ;Get pointer to start of free space
MOVL R4,XCTADR[R2] ;Save as target pointer
CLRL R0 ;Clear parenthetical counter
XCWRT1: MOVZBL (R6)+,R1 ;Get a character
XCWRT1A:TSTB R1 ;Check for null (needed for xfer from XCWRPX)
BNEQ 10$
BRW XCWEND ;Done if null
10$: CMPB R1,#^A" " ;Some control character?
BLSS XCWRT1 ;Yes - ignore it
CMPB R1,#^A"^" ;Some command?
BEQL XCWCMD ;Yes - pursue it
CMPB R1,#^A"$" ;Enter (or escape)?
BNEQ 20$
MOVB #^O33,R1 ;Yes - set it up
20$: CMPB R1,#^A")" ;Maybe the end of a conditional?
BNEQ XCWRT2
TSTL R0 ;If so, end the block
BLEQ XCWRT2
BRW XCWRPE
XCWRT2: BSBW XCTWO1 ;Save character
BRB XCWRT1 ; and get another
XCWCMD: MOVZBL (R6)+,R1 ;Get 1st letter of command name
CMPB R1,#^A"$" ;Really want a real dollar-sign?
BEQL XCWRT2 ;Yes - just save it
CMPB R1,#^A")" ; or close paren?
BEQL XCWRT2 ;Yes - just save it
CMPB R1,#^A"^" ;Really want an up-arrow?
BNEQ 10$
BSBW XCTWO1 ;Yes - just go save it twice
BRB XCWRT2
10$: CMPB R1,#^A"9" ;No - got a repeat count?
BGTR 20$ ;No
BRW XCWRPT ;Yes - set count up
20$: MOVL #^A"^ ",XCTTMP ;Prepare to get command
MOVAB XCTTMP+1,R2
BSBB XCWGET1 ;Put new character in with it
BSBB XCWGET ;Get rest of command name
CMPL XCTTMP,#^A"^RF " ;Got a roll forward?
BEQL XCWRT3 ;Yes
CMPL XCTTMP,#^A"^RB " ; or a roll backward?
BEQL XCWRT3 ;Yes
XCWRT4: MOVL XCTTMP,R2 ;Get the command name
MOVL #<CMDLEN/4>-1,R1 ;Look for command among names
10$: CMPL R2,CMDNAM[R1] ;Is this it?
BEQL 20$ ;Yes
SOBGEQ R1,10$ ;No - keep looking
BRB XCWCON ;If not found, see if it's a conditional
20$: CMPL R1,#^A" " ;Got a high-numbered command?
BGEQ XCWRT5 ;Yes
BRB XCWRT2 ;No - O.K.
XCWRT5: MOVZBL #^A"^",R2 ;Yes - precede it with an up-arrow
BSBW XCTWO2
BRW XCWRT2 ;Then save command
XCWRT3: BSBB XCWGET ;Get rest of command name
BRB XCWRT4
XCWGET::MOVZBL (R6)+,R1 ;Get next character
XCWGET1: CMPB R1,#^A"a" ;Lower case?
BLSS 10$ ;No
SUBB #^O40,R1 ;Yes - convert to upper
10$: MOVB R1,(R2)+ ;Save character
RSB ;Done
;Conditional flags: cond; DO, FR, FC, IF, DW, NOT
;If DO flag, then rest of byte (5 bits) is high order of count
;If FC, FR, or F. then three low flags are: EQU, GRTR, NOT
;Also, 100 is end of a DO block and 101 is end of an IF
XCWCON: TSTB R1 ;Is it a reset?
BNEQ 10$ ;No
MOVZBL #^O77,R1 ;Yes - save "^", 77
BRB XCWRT5
10$: MOVZWL #CMDCLN-1,R1 ;Look for a construct among the non-commands
XCWCN0: MOVL CMDCON[R1],R3 ;Get the command
BICL #^XFF000000,R3 ;Keep only the first three characters
BISL #^X20000000,R3 ;Make the fourth character into a space
CMPL XCTTMP,R3 ;Is this it?
BEQL 10$ ;Yes
SOBGEQ R1,XCWCN0 ;No - keep looking
BRW XCWERR ;Error if not found
10$: MOVL CMDCON1[R1],R2 ;Get the type flags
BBS #6,R2,20$ ;Got a conditional?
BRW XCWCNX ;No - check further
20$: CMPL #^O102,R2 ;Got a do-while?
BNEQ 30$ ;No
MOVL #^O100,-(SP) ;Yes - stack DO's end character
BRB 40$
30$: MOVL #^O101,-(SP) ;Else stack IF's end character
40$: MOVZBL #^A"^",R1 ;Start conditional block
BSBW XCTWO1
BITL #^O30,R2 ;Got IF-ROW, -COLUMN, or -COUNTER?
BEQL XCWCN1 ;No
BRW XCWCNF ;Yes - go read condition and number
XCWCN1: MOVZBL (R6)+,R1 ;Get next character
CMPB #^A"^",R1 ;"NOT" or character class?
BEQL 10$
BRW XCWCN2 ;No - finish off
;Values are: space (5), number (3), alpha (letter) (1), upper case (6),
;alpha-numeric (4), end of line (2), character == NOT space
10$: MOVZBL (R6)+,R1 ;Get next character
CMPB #^A"(",R1 ;Got a real open paren?
BNEQ 20$
BRB XCWCN2 ;Yes - treat it like the character it is
20$: CMPB R1,#^A"A" ;Got some real letter?
BGEQ 30$ ;Yes
BRW XCWERR ;No - it's an error from the start
30$: CMPB R1,#^A"a" ;Lower case?
BLSS 40$
SUBB #^O40,R1 ;Yes - convert to upper
40$: CMPB R1,#^A"X" ;Got a 'NOT" flag?
BNEQ 50$
BISL #1,R2 ;Yes - set the flag
BRB XCWCN1 ;Go get the character or class
50$: CMPB R1,#^A"L" ;Check class: Letter?
BNEQ 60$ ;No
MOVZBL #1,R1 ;Yes - get value
BRB 130$
60$: CMPB R1,#^A"N" ;Numeric?
BNEQ 70$ ;No
MOVZBL #3,R1 ;Yes - get value
BRB 130$
70$: CMPB R1,#^A"E" ;End of line?
BNEQ 80$ ;No
MOVZBL #2,R1 ;Yes - get value
BRB 130$
80$: CMPB R1,#^A"A" ;Alpha-numeric?
BNEQ 90$ ;No
MOVZBL #4,R1 ;Yes - get value
BRB 130$
90$: CMPB R1,#^A"U" ;Upper case?
BNEQ 100$ ;No
MOVZBL #6,R1 ;Yes - get value
BRB 130$
100$: CMPB R1,#^A"C" ;Any character?
BNEQ 110$ ;No
BISL #1,R2 ;Yes - set "NOT" and space value
BRB 120$
110$: CMPB R1,#^A"S" ;Space character?
BNEQ 130$
120$: MOVZBL #5,R1 ;Yes - set value
130$: CMPL R1,#6 ;Got a legal value?
BLEQ 140$ ;Yes
BRW XCWERR ;No - mistake
140$: BSBW XCTWO2 ;Save flags
MOVZBL #^A"^",R2 ;Save class flag
XCWCN2: BSBW XCTWO2
BSBW XCTWO1 ;Save class to look for
MOVZBL (R6)+,R1 ;Get character after conditional
BRW XCWRPX ;Skip "(", if any, and loop
XCWCNX: MOVZBL #^A"^",R1 ;Save an up-arrow
BSBW XCTWO1
BSBW XCTWO2 ;Then save command
CMPL R2,#^O16 ;Is it output?
BEQL XCWCXO ;Yes - read and set up the string
CMPL R2,#^O15 ;Is it initialize?
BEQL XCWCX1 ;Yes
CMPL R2,#^O21 ; or do-on-search-failure?
BEQL XCWCX1 ;Yes - go stack
CMPL R2,#^O10 ;Is it iterate-counter?
BEQL XCWCX1 ;Yes
BRW XCWRT1 ;No - loop
XCWCX1: MOVL #^O100,-(SP) ;Yes - stack the end-repeat character
MOVZBL (R6)+,R1 ;Get next character
BRW XCWRPX ;Skip "(", if any, and loop
;Here for the output construct - save characters until a ")"
XCWCXO: MOVZBL (R6)+,R1 ;Get the "(" after the "^OU"
CMPB R1,#^A"(" ;Is it really an open paren?
BEQL XCWXO1 ;Yes
BRW XCWERR ;No - error
XCWXO1: MOVZBL (R6)+,R1 ;Get a character to output
BNEQ 10$
BRW XCWERR ;Error if end of buffer reached
10$: CMPB R1,#^A")" ;End of string?
BEQL XCWXOE ;Yes - finish off
CMPB R1,#^A"$" ;Want an escape?
BNEQ 20$ ;No
MOVZBL #^O33,R1 ;Yes - get one
20$: CMPB R1,#^A"^" ;Want a control character?
BNEQ 30$ ;No
BSBB XCWXOC ;Yes - convert the next character
30$: BSBW XCTWO1 ;Save the character
BRB XCWXO1 ;And get another
XCWXOE: MOVZBL #^O177,R1 ;End the string
BSBW XCTWO1
BRW XCWRT1 ;and get more input
XCWXOC: MOVZBL (R6)+,R1 ;Get the control character
CMPB R1,#^A"$" ;Want a real dollar sign?
BEQL 10$
CMPB R1,#^A")" ; or close paren?
BEQL 10$ ;Yes - go save it
BICB #^C^O37,R1 ;No - make it a control character
10$: RSB ;Return to save it
;Here for IF-ROW, -COLUMN or -COUNTER
XCWCNF: MOVZBL (R6)+,R1 ;Get condition of the if (G, L, E, N)
CMPB R1,#^A"a" ;Lower case?
BLSS 10$
SUBB #^O40,R1 ;Yes - convert to upper
10$: CMPB R1,#^A"G" ;Greater?
BNEQ 20$ ;No
BISL #2,R2 ;Yes - set flag
BRB 60$
20$: CMPB R1,#^A"L" ;Less?
BNEQ 30$ ;No
BISL #3,R2 ;Yes - set flags
BRB 60$
30$: CMPB R1,#^A"E" ;Equal?
BNEQ 40$ ;No
BISL #4,R2 ;Yes - set flag
BRB 60$
40$: CMPB R1,#^A"N" ;Not equal?
BEQL 50$
BRW XCWERR ;No - error
50$: BISL #5,R2 ;Yes - set flags
60$: MOVZBL (R6)+,R1 ;Yes - get first digit of row or column
BRB XCWRP0 ;Read and save number of row or column
XCWRPT: MOVL #^O100,-(SP) ;Stack the end-repeat character
MOVZBL #^A"^",R2 ;Announce start of count
BSBW XCTWO2
MOVZBL #^O140,R2 ;Get flags to indicate a "do"
XCWRP0: CLRL R3
SUBB3 #^O60,R1,R3 ;Convert character to a digit
BGEQ XCWRP1
BRW XCWERR ;Error if not numeric
XCWRP1: MOVZBL (R6)+,R1 ;Get next character
CMPB R1,#^A"9" ;Numeric?
BGTR XCWRP2
CMPB R1,#^A"0"
BLSS XCWRP2 ;No - end the count
SUBL #^A"0",R1 ;Convert to a digit
MULL #10,R3 ;Shift over the old stuff
ADDL R1,R3 ;Put the new digit in
BRB XCWRP1 ; and get another one
XCWRP2: BBC #6,R2,XCWRP3 ;Got DO, or FR/FC/F.?
ROTL #-7,R3,R3 ;No - get high order count bits
BISB R3,R2 ;Set them in flag word
ROTL #7,R3,R3 ;Get low bits back
XCWRP3: BSBB XCTWO2 ;Save flags and high bits
BSBB XCTWO3 ;Save rest of repeat count
XCWRPX: INCL R0 ;Count the level
CMPB R1,#^A"(" ;Got start of the repeat block?
BNEQ 10$ ;No
BRW XCWRT1 ;Yes - ignore it
10$: BRW XCWRT1A ;Else process the character, whatever it is
XCWRPE: MOVZBL #^A"^",R1 ;Mark the end of the repeat section
BSBB XCTWO1
MOVL (SP)+,R1 ;Get flavor of repeat
BSBB XCTWO1 ;Store it
DECL R0 ;Get next character
BRW XCWRT1
XCWEND: CLRB (R4)+ ;End buffer with a null
MOVB #-1,(R4)+ ;and set end-of-data flag
MOVL R4,XCFPTR ;Save it
MOVL XCTLVL,R1 ;Get overflow flag
CLRL XCTLVL ; and clear it
TSTL R1 ;Did it overflow?
BGEQ 10$ ;No
BRW XCVERR ;Yes - error
10$: TSTL R0 ;Some conditional not closed?
BGTR XCWEN1
BBSC #V_FLG,F,20$ ;Want to return (to SWHMNY)?
BRW XCTEND ;No
20$: RSB ;Yes
XCWEN1: MOVL (SP)+,R1 ;Pop save conditionals off stack
SOBGTR R1,XCWEN1
MOVAB XCNMS1,R1 ;Then give error message
BRW ERROR
XCWERR: MOVAB XCWERM,R1
BRW ERROR
XCTWO3: MOVB R3,(R4)+ ;Output character in R3
BRB XCTWOU
XCTWO2: MOVB R2,(R4)+ ;I mean in R2
BRB XCTWOU
XCTWO1: MOVB R1,(R4)+ ;I mean in R1
XCTWOU: CMPL R4,XCTOVF ;Is buffer about to overflow?
BNEQ 10$ ;No - O.K.
MOVB #-1,(R4) ;Light end-of-data bit
BSBB XCGARB ;Do a garbage collect
DECL R4 ;Point back to where we belong
CLRB (R4) ;Clear the end-of-data bit
CMPL R4,XCTOVF ;Was anything recovered?
BNEQ 10$ ;Yes - done
MOVL XCTACW,R4 ;No - reset current write pointer
MOVL XCTADR[R4],R4
CVTBL #-1,XCTLVL ;Note that buffer oveflowed
10$: RSB ;Read rest of buffer
;Subroutine to garbage collect the execute free space
;Returns pointer to lowest free address in R4
;Uses R0-R3
XCGARB: PUSHR #^M<R0> ;Save the level counter
MOVAB XCTFRE,R4 ;Point to start of free space
XCGAR1: CVTBL #-1,R0 ;Look for smallest pointer - start big
MOVL #XBFNUM-1,R3 ;Look through all buffer pointers
XCGAR2: MOVL XCTADR[R3],R1 ;Is this pointer active?
BEQL XCGAR3 ;Not active
CMPL R4,R1 ;Yes - is address greater than start of F.S.?
BGTR XCGAR3 ;Too small - get another
CMPL R0,R1 ;Is address less than lowest so far?
BLEQU XCGAR3 ;No - skip it
MOVL R1,R0 ;Yes - save new one instead
MOVL R3,R2 ;Save index, too
XCGAR3: SOBGEQ R3,XCGAR2 ;Loop through all pointers
CMPL #-1,R0 ;Is there a lowest pointer?
BNEQ 10$ ;Yes
POPR #^M<R0> ;Restore the level number
RSB ;No - return
10$: MOVL R0,R3 ;Get the address
MOVL R4,XCTADR[R2] ;Save new pointer to buffer data
XCGAR4: MOVB (R3)+,(R4)+ ;Transfer a byte
CMPB #^XFF,-1(R4) ;End of the data?
BNEQ XCGAR4 ;No
CMPL R3,R4 ;Done moving - was it really a move?
BEQL XCGAR1 ;No
CLRB -1(R3) ;Yes - clear flag in old last byte
BRB XCGAR1
XCNMS1: .ASCIZ /###Conditional block not closed/
XCWERM: .ASCIZ /#########Bad command name/
;Here to write the active buffer
;and then execute it the given number of times
XCTXCT: BBCC #V_XSV,F1,10$ ;Was a buffer open?
BSBW XCTWIP ;Yes - close it
10$: MOVAB PARBUF+1,R6 ;Point to 2nd character of parameter
MOVAB PARBUF,R4 ; and to its start
XCTXC1: MOVZBL (R6)+,R1 ;Shift execute count left a notch
CMPB R1,#^A"0" ;Is this a digit?
BLSS XCTXC2
CMPB R1,#^A"9"
BGTR XCTXC2 ;No - got it all
MOVB R1,(R4)+ ;Yes - save it and get more
BRB XCTXC1
XCTXC2: CMPB R1,#^A":" ;Does the number end with a colon?
BEQL 10$
DECL R6 ;No - back up over the latest character
10$: CLRB (R4)+ ;End count with a null
BISL #M_FLG,F ;Set to get a return from XCTWRT
BSBW XCWRT0 ;Write into the buffer
BRW EXCUT0 ;Set up and execute the new buffer
;Here to output the contents of the active buffer in write format
XCTRDW: CMPL #PARBUF+1,PARPTR ;Has a name been given?
BEQL XCRDWC ;No - read the active buffer
BISL #M_FLG,F ;Yes - set up that buffer first
BSBW XCTSET
XCRDWC: BBCC #V_XSV,F1,10$ ;Saving commands?
BSBW XCTWIP ;Yes - stop, and wipe out this one
10$: MOVL XCTACW,R6 ;Point to the active buffer
BGEQ 20$ ;Any there?
BRW XCOERR ;No - error
20$: MOVL XCTADR[R6],R6 ;Yes - get pointer
MOVAB PARBUF,R5 ;Write to parameter buffer
MOVB #^A"W",(R5)+ ;Start it off
BRB XCRDLT ;Go output the buffer's contents
;Here to output name and contents of active buffer in switch format
XCTRDL: CMPL #PARBUF+1,PARPTR ;Has a name been given?
BEQL XCRDLC ;No - read the active buffer
BISL #M_FLG,F ;Yes - set up that buffer first
BSBW XCTSET
XCRDLC: BBCC #V_XSV,F1,10$ ;Saving commands?
BSBW XCTWIP ;Yes - stop, and wipe out this one
10$: MOVL XCTACW,R2 ;Get name of active execute buffer
BGEQ 20$ ;Any?
BRW XCOERR ;No - error
20$: MOVAB PARBUF,R5 ;Write to parameter buffer
MOVL #^A"/X",R1 ;Start it off
JSB PUTSQ1
MOVL XCTADR[R2],R6 ;Get pointer to buffer
MOVAQ XCTNAM[R2],R1 ;Get pointer to name
TSTL (R1) ;Is name null?
BEQL 30$ ;Yes
JSB PUTSTG ;No - output it
30$: MOVQ XCTKEY[R2],R0 ;Got a key sequence, too?
BEQL 40$ ;No
BSBW XCTRDK ;Yes - output it
40$: MOVB #^A":",(R5)+ ;Separate name and contents
XCRDLT: TSTL R6 ;Is there anything in the buffer?
BNEQ XCRDL0 ;Yes
BRW XCREND ;No - go finish off
XCRDL0: MOVZBL (R6)+,R1 ;Get a character
BNEQ 10$ ;If null, finish off
BRW XCREND
10$: CMPB R1,#^A"^" ;Special flag?
BEQL XCRSPC ;Yes - handle separately
CMPB R1,#^A" " ;Control character?
BLSS XCRCTL ;Yes - handle separately
CMPB R1,#^A"$" ;Want a real dollar sign?
BNEQ XCRDL1 ;No
MOVB #^A"^",(R5)+ ;Yes - display it as up-arrow dollar sign
XCRDL1: MOVB R1,(R5)+ ;Output character
BRB XCRDL0 ;and get another
XCRSPC: MOVZBL (R6)+,R1 ;Get character after special flag
CMPB R1,#^A"^" ;Want a real up-arrow?
BNEQ 10$ ;No
MOVB R1,(R5)+ ;Yes - output two arrows to show it's real
BRB XCRDL1
10$: CMPB R1,#^O77 ;Reset command?
BNEQ 20$ ;No
CLRL R1 ;Yes - get the right code
BRB XCRCTL
20$: BBC #6,R1,30$ ;Got some kind of conditional?
BRW XCRRPT ;Yes
30$: CMPB R1,#^O40 ;Got an exit or continue, or other?
BLSS XCRCON ;Yes - get string from conditional table
XCRCTL: MOVL CMDNAM[R1],R1 ;Get command name
XCRCT1: BSBW PUTSPCL ;Output it
BRB XCRDL0 ;Back to the flow
XCRCON: MOVL CMDCON[R1],R1 ;Get string from the conditional table
CMPL R1,#^A"^OU(" ;Got an output command?
BNEQ XCRCT1 ;No - process it normally
JSB PUTSQ1 ;Yes - output it
XCRCN1: MOVZBL (R6)+,R1 ;Get a character of the output string
CMPB R1,#^O177 ;End of string?
BEQL XCRCNE ;Yes - finish off
CMPB R1,#^A"$" ;Got a real dollar sign?
BEQL 10$ ;Yes
CMPB R1,#^A")" ;or close paren?
BNEQ 20$ ;No
10$: MOVB #^A"^",(R5)+ ;Yes - precede with an up-arrow
20$: CMPB R1,#^O40 ;Control character?
BGEQ 30$
BSBB XCRCNC ;Yes - output specially
30$: MOVB R1,(R5)+ ;Output the character
BRB XCRCN1 ;and get more
XCRCNE: MOVB #^A")",(R5)+ ;End string with a close paren
BRW XCRDL0 ;And get more of the buffer
XCRCNC: CMPB R1,#^O33 ;Escape?
BNEQ 10$ ;No
MOVZBL #^A"$",R1 ;Yes - output as a dollar sign
RSB
10$: MOVB R2,(R5)+ ;No - precede with an up-arrow
ADDB #^O100,R1 ;Make the control character visible
RSB ;Done
XCREND: SUBL3 #PARBUF,R5,R1 ;Get length of the parameter
CMPL #TYPSIZ,R1 ;Is it too much to type out?
BGEQ 10$ ;No - continue
MOVAB PARBUF+TYPSIZ,R5 ;Yes - truncate it
10$: CLRB (R5) ;End with a null
MOVL R5,PARPTR ;Save type pointer as parameter pointer
MOVAB TYPBUF,R5 ;Point back to type buffer
BRW RECALL ;Pretend this was the last param typed
XCTRDK: MOVB #^A",",(R5)+ ;Output the separator
MOVAQ XCTKEY[R2],R1 ;Point to the key sequence
MOVL R4,-(SP) ;Save a register
CLRL R4 ;Clear the byte counter
XCTRK1: MOVZBL (R1)+,R0 ;Get a character
BEQL XCTRK2 ;Done if character is null
CMPB R0,#^O177 ;Got a rubout?
BEQL 10$
BITB #^O140,R0 ; or a control character?
BNEQ 30$ ;No
10$: MOVB #^A"^",(R5)+ ;Yes - simulate as up-arrow character
CMPB R0,#^O177 ; (Rubout as up-arrow "?")
BEQL 20$
BISB #^O100,R0 ;Convert to a printable character
BRB 30$
20$: MOVB #^A"?",R0
30$: MOVB R0,(R5)+ ;Output the character
ACBB #8,#1,R4,XCTRK1
XCTRK2: MOVL (SP)+,R4 ;Restore R4
RSB ;Then done
;Here if some kind of conditional is found
XCRRPT: BITB #^O76,R1 ;Ending a repeat block?
BNEQ 10$
BRW XCRRPE ;Yes - do so
10$: BBC #5,R1,20$ ;Got an iterated do?
BRW XCRRPD ;Yes - handle specially
20$: BITB #^O30,R1 ;Got an if-row, -column, or -counter?
BEQL 30$ ;No
BRB XCRRPF ;Yes - handle specially
30$: BBC #2,R1,40$ ;Got an if-character?
MOVL CMDCON+12,R2 ;Yes - get its sequence
BRB 50$
40$: MOVL CMDCON+16,R2 ;No - get sequence for do-while
50$: MOVL R2,R0 ;Get ready to output the sequence
MOVL R1,R2
MOVL R0,R1
BSBW PUTSPCL ;Output the sequence
BBC #0,R2,60$ ;Want a "not" flag?
MOVL #^A"^X",R1 ;Yes - output it
BSBW PUTSPCL
60$: MOVZBL (R6)+,R1 ;Get character to condition on
CMPB R1,#^A"(" ;Is it a real open paren?
BNEQ 70$
MOVB #^A"^",(R5)+ ;Yes - lead it off with an up-arrow
70$: MOVB R1,(R5)+ ;Output the condition
CMPB R1,#^A"^" ;Want a class of characters?
BNEQ XCRRPX ;No
MOVZBL (R6)+,R1 ;Yes - get class
MOVB XCTCLS-1[R1],(R5)+ ; and output it
XCRRPX: MOVB #^A"(",(R5)+ ;Start off the repeat block
BRW XCRDL0 ;and back to the flow
XCRRPF: BBC #3,R1,10$ ;Got an if-column?
MOVL CMDCON+4,R2 ;Yes - get its sequence
BRB 20$
10$: MOVL CMDCON,R2 ;No - get sequence for if-row
20$: CMPB R1,#^O130 ;Or is it really an if-counter?
BLSS 30$
MOVL CMDCON+8,R2 ;Yes - get the real sequence
30$: MOVL R1,-(SP) ;Save the command
MOVL R2,R1 ;Get the sequence
BSBW PUTSPCL ;Output it
MOVL (SP)+,R2 ;Get the command again
BICB #^C7,R2 ;Isolate the condition type
MOVB XCTREL-2[R2],(R5)+ ;Output the condition
MOVZBL (R6)+,R1 ;Get row or column number
BRB XCRPD1 ;Output it and finish off
XCRRPD: MOVB #^A"^",(R5)+ ;Flag number as a count
BICL #^C^O37,R1 ;Isolate the high-order bits
ASHL #7,R1,R1 ;Position them
MOVZBL (R6)+,R2 ;Get the low order bits
ADDL R2,R1 ;Build the full number
XCRPD1: JSB PUTNUM ;Output it
BRB XCRRPX ;Save character and flow
XCRRPE: MOVZBL #^A")",R1 ;End the repeat block
BRW XCRDL1 ;Save character and flow
;Here to output list of defined names
XCTNML: BSBW SWHBOT ;Set up the bottom line
MOVL #XBFNUM-1,R2 ;Look for name of buffer
MOVL XCTACW,R4 ;Get the pointer to the currently active buffer
10$: MOVQ XCTNAM[R2],XCTTMP ;Get a name
BNEQ 30$ ;Any? Yes
20$: SOBGEQ R2,10$ ;No - loop thru list
BRW SWHNPE ;When done, finish off like the switch info
30$: CMPL R4,R2 ;Else is this the active buffer?
BNEQ 35$ ;No
MOVB #^A"*",(R5)+ ;Yes - mark it as such
35$: BICB #1,XCTTMP+7 ;Clear the flag bit in name
TSTL XCTTMP ;Is this the null buffer?
BNEQ 40$ ;No
TSTL XCTTMP+4
BNEQ 40$
MOVQ #^A"<NUL>",XCTTMP ;Yes - set up null name
40$: MOVAB XCTTMP,R1 ;Point to the string
JSB PUTSTG ;Output name
MOVZBL #^A" ",R1 ;Separate name from next name
JSB PUTSQ1
BRB 20$ ;Get next name
;Subroutine to read the buffer name and find it among XCTNAM
;Returns name in XCTTMP; index in R1. R1/-1 if not found
XCTRED: MOVAB XCTTMP,R6 ;Get pointer to target
MOVAB PARBUF+1,R2 ; and source of name
CLRL XCTTMP ;Clear target - name will have low bit on
MOVL #^X01000000,XCTTMP+4
MOVZBL #5,R3 ;Read at most 5 characters
10$: MOVZBL (R2)+,R1 ;Get next character
BEQL 20$ ;Done if null
CMPB R1,#^A"a" ;Lower case?
BLSS 15$ ;No
SUBB #^O40,R1 ;Yes - convert to upper
15$: MOVB R1,(R6)+ ;Store it in target
SOBGTR R3,10$ ;Decrement count, get another char if needed
20$: MOVL #XBFNUM-1,R4 ;Now look for name
30$: MULL3 #8,R4,R3 ;Compute the offset
CMPL L^XCTNAM(R3),XCTTMP ;Is this it?
BNEQ 35$ ;No
CMPL L^XCTNAM+4(R3),XCTTMP+4 ;Check the second half
BEQL 40$ ;This is it
35$: SOBGEQ R4,30$ ;No - loop
40$: MOVL R4,R1 ;Return value in the right place
RSB
;Here to link current execute buffer to the push of a button
XCTBTN: BBCC #V_XSV,F1,10$ ;Was a buffer open?
BSBW XCTWIP ;Yes - close it
10$: MOVAB XCBMSG,R1
JSB PUTBTM ;Put message on bottom line
JSB PROTOF ;Unprotect
JSB PUTTYP ;Output all this now
MOVL #^O1001,R9 ;Note that it's button time
MOVL XCTACW,R2 ;Point to active execute buffer
MOVL XCTADR[R2],R6 ;Get pointer to buffer data
BSBW XCTKLK ;Clean out old key, if any
MOVAQ XCTKEY[R2],R6 ;Make a ptr which doesn't use R2
MOVL R6,SAVEAC+20 ;Save it also for later
BISL #^X8000,R2 ;Set execute bit
MOVL R2,SAVEAC+24 ; and save for SUBTBX
CLRL R3 ;Set up the character counter
XCTBT1: $QIOW_S FUNC=#IO$_TTYREADALL!IO$M_NOECHO,-
CHAN=TTCHAN,- ;Read a character from the terminal
P1=TTYBUF,-
P2=#1
MOVZBL TTYBUF,R1 ;Get the character
CMPB R1,#^A"G" ;End of command?
BEQL XCTBT3
CMPB R1,#^A"g"
BEQL XCTBT3 ;Yes - finish off
INCL R3 ;Already got 8 characters?
CMPL R3,#8
BGTR XCTBT1 ;Yes - ignore it
MOVB R1,(R6)+ ;No - save character
BRB XCTBT1
XCTBT3: MOVL SAVEAC+20,R6 ;Get pointer to execute command sequence
TSTL (R6) ;Got a sequence?
BEQL 10$
BSBW SUBTBX ;Yes - if it's legal change input table
10$: BRW XCTEND ;Done
XCBMSG: .ASCIZ /Push any command button, then "G": /
;Here to read a file of execute buffer switches
;Current buffers are replaced by these
XCTBSW: BBCC #V_XSV,F1,10$ ;Was a buffer open?
BSBW XCTWIP ;Yes - close it
10$: MOVAB PARBUF+1,R6 ;Prepare to get the filename
MOVAB XCTFIL,R3
CLRL R4 ;Clear the count
20$: MOVB (R6)+,(R3)+ ;Transfer a character
BEQL 30$ ;End of the string? Yes
INCL R4 ;No - count the character
BRB 20$ ;and loop until finished
30$: $FAB_STORE FAB=XCT_FAB,FNS=R4 ;Save the length of the filespec
CLRW XCT_FAB+FAB$W_IFI
$OPEN FAB=XCT_FAB ;Open the file
BLBS R0,40$ ;Was it successful?
35$: BRW XCIERR ;No - error
40$: $CONNECT RAB=XCT_RAB ;Connect the record stream
BLBC R0,35$ ;Check for errors
XCTSB0: BSBW PIKFRG ;Make sure the pick buffer is not fragged
MOVL XCT_XAB+XAB$L_EBK,R1 ;Get end of file block number
MULL #^X200,R1 ;Compute bytes to read
CMPL R1,#PCBSIZ ;Is it too large?
BLEQ 10$ ;No
MOVL #PCBSIZ,R1 ;Yes - truncate it
10$: $RAB_STORE RAB=XCT_RAB,RBF=#0,RSZ=#0,UBF=PIKBUF,USZ=R1,BKT=#1
$READ RAB=XCT_RAB
BLBS R0,20$
BRW XCIERR
20$: $DISCONNECT RAB=XCT_RAB
$CLOSE FAB=XCT_FAB
SUBL3 #1,XCT_XAB+XAB$L_EBK,R1 ;Compute the ending byte address
MULL #^X200,R1
ADDW XCT_XAB+XAB$W_FFB,R1
ADDL3 #PIKBUF,R1,END_INI
MOVL #XBFNUM-1,R2 ;Zero all existing information
30$: BSBW XCTKLL
SOBGEQ R2,30$
MOVAB XCTFRE,XCFPTR ;All buffer space is now free
MOVAB PIKBUF,R2 ;Point to the buffer
MOVZWL PIKBUF,SAVEAC ;Save the byte count
MOVL R2,SAVEAC+4 ; and its address
XCTSB1: MOVL SAVEAC+4,R2 ;Get address and byte count of next line
MOVL SAVEAC,R3
CMPW #-1,R3 ;If byte count = -1, end of file
BNEQ 20$
10$: BRW XWFERR ;End - error - wrong format
20$: CMPL R2,END_INI ;Or if at the end of data, call it end of file
BGEQ 10$
ADDL R2,R3 ;Compute address of next line
ADDL #2,R3
BBC #0,R3,30$ ;At an odd address?
INCL R3 ;Yes - step to the next one
30$: MOVL R3,SAVEAC+4 ;Save it for next time
MOVZWL (R3),SAVEAC ;Also save the byte count
CLRW (R3) ;Make sure line ends with a null
ADDL #2,R2 ;Go to the start of the line
XCTSB2: MOVZBL (R2)+,R1 ;Get a character of the file
BEQL XCTSB1 ;If null, we're at end of the line
CMPB R1,#^A"/" ;Is it a switch?
BNEQ XCTSB2 ;No - loop until start of switches
XCTSB3: BSBW SWHMNY ;Go parse the switches
5$: MOVL SAVEAC+4,R2 ;Get address & byte count of next line
MOVL SAVEAC,R3
CMPW #-1,R3 ;If byte count = -1, end of file
BEQL 20$
CMPL R2,END_INI ;Or if at end of the data, call it end of file
BGEQ 20$
ADDL R2,R3 ;Compute address of the next line
ADDL #2,R3
BBC #0,R3,10$ ;At an odd address?
INCL R3 ;Yes - step to the next one
10$: MOVL R3,SAVEAC+4 ;Save it for next time
MOVZWL (R3),SAVEAC ;Also save the byte count
CLRW (R3) ;Make sure line ends with a null
ADDL #2,R2 ;Go to the start of the line
TSTB (R2) ;Is the first byte blank?
BEQL 5$ ;Yes - this line is empty
MOVZBL (R2)+,R1 ;Get the first byte of the line
CMPB R1,#^A"/" ;Is it another switch?
BEQL XCTSB3 ;Yes - go process it
20$: BBSC #V_FLG,F,30$ ;Called by SWHMNX?
BRW XCTEND ;No - finish off
30$: RSB ;Yes - return to it
;Execute, no parameter: if buffer is open, just close it
;If already closed, set to do same number of iterations as last time
EXCNPM::BBCC #V_XSV,F1,EXCNP1 ;Saving commands?
MOVL XCTPTW,R6 ;Yes - get pointer to end of buffer
BSBW XCTCLO ;Close off the buffer
JMP LOOP ;and get a new command
EXCNP1: MOVL XCTITR,R3 ;Get number of iterations
MOVL R3,R4 ;Any?
BLEQ 10$ ;No
BRW EXCUT1 ;Yes - go set it up
10$: MOVAB XERNP1,R1 ;No - error
JMP ERROR
XERNP1: .ASCIZ /####Enter number of iterations/
;Get a command from the execute buffer, from LOOP
XCTGET::BBC #V_JRC,F1,10$ ;Is this a journal restore?
JMP LOPJRN ;Yes - get the chraacter from the journal
10$: MOVZBL @XCTPTR,R1 ;Get a command from read buffer
INCL XCTPTR
CMPB R1,#^A"^" ;Special character flag?
BNEQ 20$ ;No
BRW XCTGT1 ;Yes - handle specially
20$: TSTB R1 ;Got a real character?
BEQL XCTGT0 ;No
BRW XCTGTE ;Yes - use it
XCTGT0: MOVL XCTACR,XCTPTR ;Else point back to start of buffer
SOBGTR XCTNUM,10$ ;Else want to do another iteration?
BRW XCTDUN ;No - finish off or pop a level
10$: BSBB XCTWIS ;Yes - may want to whistle
BRB XCTGET ;Go get first command
XCTWIS: BBS #V_XBN,F1,XCTSTP ;Don't whistle if displaying the execute
BITL #^X0F,XCTNUM ;or if not at multiple of 16th pass
BNEQ XCTSTP
MOVB #7,ECHBUF ;Output a bell
$QIOW_S CHAN=TTCHAN,-
FUNC=#IO$_WRITEVBLK!IO$M_NOFORMAT,-
P1=ECHBUF,-
P2=#1
XCTSTP: JSB SRCIPT ;Does the user want to abort the execute?
BLBC R0,10$ ;No
BRW XABERR ;Yes - do so
10$: RSB ;No
XCTGTE::CMPB R1,#^A" " ;Some control character?
BGEQ 10$ ;No
JMP LOOP2 ;Yes - handle it
10$: JMP ALPNUM ;No - just put it in file or buffer
XCTGT1: MOVZBL @XCTPTR,R1 ;Get character after the up-arrow
INCL XCTPTR
CMPB R1,#^A"^" ;Want a real up-arrow?
BNEQ 10$ ;No
JMP ALPNUM ;Yes - treat it like a normal character
10$: CMPB R1,#^O77 ;Got a reset command?
BNEQ 20$
CLRL R1 ;Yes - get the real code and dispatch
JMP LOOP2
20$: CMPB R1,#^O40 ;Got an exit or continue, or something?
BGEQ 30$
BRW XCTGCT ;Yes - go handle it
30$: BBS #6,R1,40$ ;Got the start or end of a repeat?
JMP LOOP2 ;No - process the command
40$: BITB #^O76,R1 ;End of a repeat?
BNEQ 50$ ;No
BRW XCTGRX ;Yes - go handle it
;Here if some kind of conditional
50$: BBS #5,R1,XCGITR ;Got an iterated do? Yes
BITB #^O30,R1 ;Got an if-row, -column or -counter?
BEQL 60$
BRW XCGTRC ;Yes
60$: BSBW MAKCPT ;No - re-make the character pointer
MOVZBL @XCTPTR,R2 ;Get character or class to check for
INCL XCTPTR
CMPB R2,#^A"^" ;Got a class?
BNEQ 70$ ;No
BISL #^X4000,R1 ;Yes - set class flag
70$: BSBW XCTCHK ;See if condition is true
BBC #2,R1,80$ ;Got an if-character?
BRW XCGTIF ;Yes
;Here for do-while
80$: TSTL R0 ;Was it false?
BEQL 90$ ;No
BRW XCTSKB ;Yes - skip the block
90$: MOVL R1,R3 ;Set up the flags
BISW #^X8000,R3 ;Set the do-while flag
BRB XCGIT1
;Here for iterated DO
XCGITR: MOVZBL @XCTPTR,R2 ;Get the low bits of repeat count
INCL XCTPTR
BICL #^C^X1F,R1 ;Put the high-order bits in, too
BISL R1,R2
CLRL R3 ;Clear the flags
XCGIT1: TSTL R2 ;If zero iterations, just skip the block
BNEQ 10$
TSTL R3
BNEQ 10$
BRW XCTSKB
10$: INCL XCTLVL ;Drop down a level of nesting
CMPL XCTLVL,#1 ;Now at level one?
BEQL 20$ ;Yes - don't save
MOVL XCTRPR,-(SP) ;Save ptr to start of block
MOVL XCTRPT,-(SP) ;Save previous repeat count
20$: MOVW R2,XCTRPT ;Save count
MOVW R3,XCTRPT+2 ; and flags
MOVL XCTPTR,XCTRPR ;Save pointer to start of block
BRW XCTGET ;Pick up the first iteration
;Here for IF-ROW, IF-COLUMN, IF-COUNTER, and IF-CHARACTER (XCGTIF)
XCGTRC: BBS #3,R1,10$ ;Got an if-column?
MOVL R7,R3 ;No - get row for comparison
BRB 20$
10$: MOVL R8,R3 ;Yes - get column for comparison
20$: MOVZBL @XCTPTR,R2 ;Get value to compare with
INCL XCTPTR
CMPB R1,#^O130 ;Is it really an if-counter?
BLSS 30$
MOVL XCTCTR,R3 ;Yes - get the counter
BRB 40$
30$: DECL R2 ;It's one too high, since RW & CM are zero-based
40$: CLRL R0 ;Assume compare will succeed
BBC #2,R1,50$ ;Want equality?
CMPB R3,R2 ;Yes - are they equal?
BEQL 70$ ;Yes - return true
BRB 60$ ;No - return false
50$: CMPB R3,R2 ;No - is parameter greater than value?
BGTR 70$
60$: CVTBL #-1,R0 ;No - return false
70$: BBC #0,R1,XCGTIF ;Want to negate the result?
MCOML R0,R0 ;Yes
XCGTIF: TSTL R0 ;If true, keep going
BNEQ XCTSKB
BRW XCTGET
XCTSKB: BSBB XCTSKP ;Else skip over the block
TSTB R1 ;End of the buffer?
BNEQ 10$
BRW XCTGT0 ;Yes
10$: BRW XCTGET ;No - get what comes afterwards
;Here to skip to end of a block and get what follows
XCTSKP: CLRL R0 ;Clear count of blocks passed over
10$: MOVZBL @XCTPTR,R1 ;Skip over negative "IF" block
INCL XCTPTR
TSTB R1 ;Done if null
BEQL 20$
CMPB R1,#^A"^" ;Start of end of a block?
BNEQ 10$ ;No - keep skipping
MOVZBL @XCTPTR,R1 ;Yes - get following character
INCL XCTPTR
BITB #^O76,R1 ;End of a block?
BNEQ 30$ ;No - maybe drop a little deeper
SOBGEQ R0,10$ ;Yes - loop if not the right end
20$: RSB ;Else done
30$: BBC #6,R1,10$ ;If it's a command
CMPB R1,#^A"^" ; or want a real up-arrow,
BEQL 10$ ; then skip over it
INCL R0 ;Else drop a level and keep skipping
BRB 10$
;Here for an exit or continue construct
XCTGCT: CMPB R1,#7 ;Got an exit or continue?
BLEQ 10$
SUBL #8,R1 ;No - dispatch to handle it
MOVL XCTJMP[R1],R1 ;Get address to dispatch to
JMP (R1) ; and do it
10$: BNEQ 20$ ;Want to end this iteration (^XX)?
BRW XCTGTX ;Yes - pop stack and do so
20$: MOVL R1,R2 ;No - save type of construct
MOVZBL @XCTPTR,R0 ;Get the ")" that follows the command
INCL XCTPTR
BSBB XCTSKP ;Skip to the end of the block
TSTB R1 ;At end of the buffer?
BNEQ 30$
BRW XCTGT0 ;Yes
30$: CMPB R1,#^O100 ;Is this an IF construct?
BEQL 40$
BRW XCTGET
40$: CMPB R2,#6 ;No - want to exit the block (^XB)?
BEQL XCTGRX ;No - continue the block
BRB XCTGXP ;Exit the block
;Here if end of a block - ignore if ^A (IF); loop or exit if ^@ (^DO)
XCTGRX: CMPB R1,#^O100 ;End of DO block?
BEQL 10$
BRW XCTGET ;No - ignore it
10$: BBCC #V_XCI,F1,20$ ;Stop initializing?
BRW XCTGXI ;Yes - just de-bump level
20$: BSBW XCTSTP ;See if user wants to stop
TSTL XCTRPT ;Got a do-while?
BLSS XCTGXW ;Yes - check character at cursor
SOBGTR XCTRPT,XCTGXR ;No - do-itr - de-bump counter - done? No
BRB XCTGXP ;Yes - pop back a level
XCTGXR: MOVL XCTRPR,XCTPTR ;Point to start of block
BRW XCTGET ; and take commands from there
XCTGXW: BSBW MAKCPT ;Re-make character pointer
MOVZWL XCTRPT,R2 ;Get character or class to check for
MOVZWL XCTRPT+2,R1 ;Get flags
BBC #14,R1,10$ ;Got a class?
CLRL R0 ;Yes - go check the condition
BSBW XTCHC1
BRB 20$
10$: BSBW XCTCHK ;No - check the condition
20$: TSTL R0 ;True?
BEQL XCTGXR ;Yes - just do the block; else pop level
XCTGXP: TSTL XCTLVL ;Skip if the stack is clear
BEQL 10$
DECL XCTLVL ;At bottom level?
BLEQ 10$ ;Yes - just keep going
MOVL (SP)+,XCTRPT ;Else get save count (or comparator)
MOVL (SP)+,XCTRPR ; and initial repeat pointer
10$: BRW XCTGET ;And take commands from there
XCTGTX: TSTL XCTLVL ;Skip if the stack is clear
BEQL 15$
10$: SOBGTR XCTLVL,20$ ;Pop everything off the stack - any left?
15$: BRW XCTGT0 ;No - do another iteration
20$: MOVL (SP)+,XCTRPT ;Yes - pop it off
MOVL (SP)+,XCTRPR
BRB 10$ ; and try again
XCTGXI: CLRL XCTLVL ;End of XCT init - clear level
MOVL XCTACR,XCTINI ;Save real starting pointer
MOVL XCTPTR,XCTACR ;Save current pointer as starting pointer
BRW XCTGET ;Read more of buffer
;Dispatch for routines to handle special execute constructs
XCTJMP: .ADDRESS XCTG10 ;(10) Iterate-counter
.ADDRESS XCTG11 ;(11) Clear-counter
.ADDRESS XCTG12 ;(12) Bump-counter
.ADDRESS XCTG13 ;(13) De-bump-counter
.ADDRESS XCTG14 ;(14) Use-counter
.ADDRESS XCTG15 ;(15) Initialize
.ADDRESS XCTG16 ;(16) Output
.ADDRESS XCTG17 ;(17) Save-counter
.ADDRESS XCTG20 ;(20) No-display
.ADDRESS XCTG21 ;(21) Do-on-search-error
XCTG21: BSBW XCTSKP ;Not a search error, so just skip this block
BRW XCTGET ;Done
XCTG20: BBCC #V_XBN,F1,10$ ;Turn off button flag - on?
BISL #M_XCT,F1 ;Yes - turn oon normal execute flag
10$: BRW XCTGET ;Done
XCTG17: BBC #V_ENT,F,XCG17A ;Is there a parameter?
MOVL XCTSNM,R4 ;Yes - get last time's nominal
MOVL R4,PARG1
BSBW PEEL.1 ;Read new parm, if any
BBC #V_CMV,F,10$ ;Cursor movement?
MOVL PARG2,R4 ;Yes - get change in columns
BRB 20$
10$: MOVL PARG1,R4
20$: MOVL R4,XCTSNM ;Save as new nominal
JSB ERASPM ;Fix up the screen
XCG17A: MOVL XCTSNM,XCTCTR ;Save new counter value
BRW XCTGET ;Done
XCTG16: MOVZBL @XCTPTR,R1 ;Get a character to output
INCL XCTPTR
CMPB R1,#^O177 ;End of string?
BEQL XCG16A ;Yes - output it and finish off
MOVB R1,(R5)+ ;No - save the character
BRB XCTG16 ; and get another
XCG16A: JSB PUTTYP ;Output the string
BRW XCTGET ;and read more of the buffer
XCTG15: BISL #M_XCI,F1 ;Initialize - set flag
INCL XCTLVL ;Drop down a level
BRW XCTGET ;Read more of buffer
XCTG14: MOVL XCTCTR,R1 ;Get counter
BGEQ 10$ ;Is it negative?
CLRL R1 ;Yes - set to zero
10$: MOVL R5,PARPTR ;Save output pointer
MOVAB PARBUF,R5
JSB PUTNUM ;Put number in parameter buffer
MOVL R5,R1 ;Swap parameter and output pointers
MOVL PARPTR,R5
MOVL R1,PARPTR
BICL #M_PST,F1 ;Indicate that a parameter has been entered
BRW XCTGET ;Read more of buffer
XCTG13: DECL XCTCTR ;De-bump counter
BRW XCTGET
XCTG12: INCL XCTCTR ;Bump counter
BRW XCTGET
XCTG11: CLRL XCTCTR ;Clear the counter
BRW XCTGET
XCTG10: MOVL XCTCTR,R2 ;Get counter
BGEQ 10$ ;Negative?
CLRL R2 ;Yes - use zero
10$: CLRL R3 ;Clear the flags too
BRW XCGIT1 ;Use it with an iterated DO
;Subroutine to check to see if character in R3 matches char or class in R2
XCTCHK: CMPB R2,#^A"^" ;Want a class?
BEQL XCTCHC ;Yes - handle separately
CMPB R3,R2 ;No - got the right character?
BNEQ XCTCHF ;No
XCTCHT: CLRL R0 ;Yes - flag as true
BRB XCCHND
XCTCHF: CVTBL #-1,R0 ;No - flag as false
XCCHND: BBC #0,R1,10$ ;Got .NOT. flag?
MCOML R0,R0 ;Yes - return the opposite result
10$: RSB ;Done
XCTCHP: MOVL SAVEAC,R1 ;Restore saved R1
BRB XCCHND ; and go complement flag if needed
XCTCHC: MOVZBL @XCTPTR,R2 ;Get class to check for
INCL XCTPTR
XTCHC1: CMPB R2,#2 ;End of line?
BEQL XCTCHE ;Yes
CMPB R2,#3 ;Number?
BEQL XCTCHN ;Yes
CMPB R2,#5 ;Space?
BEQL XCTCHS ;Yes
CMPB R3,#^A"A" ;Check for upper, letter or alpha-num
BLSS XCTCHM ;Not letter - may be number
CMPB R3,#^A"Z" ;Letter?
BLEQ XCTCHT ;Yes - return true
CMPB R2,#6 ;Looking for upper case?
BEQL XCTCHF ;Yes - return false
CMPB R3,#^A"a" ;No - is it lower case?
BLSS XCTCHF ;No - return false
CMPB R3,#^A"z"
BLEQ XCTCHT
BRB XCTCHF ;Yes - return true
XCTCHM: CMPB R2,#4 ;Not alpha - want alpha-num?
BNEQ XCTCHF ;No - return false
XCTCHN: CMPB R3,#^A"0" ;Check for number - is it?
BLSS XCTCHF
CMPB R3,#^A"9"
BGTR XCTCHF ;No - return false
BRB XCTCHT ;Yes - return true
XCTCHS: BBC #1,R1,XCCHSS ;Checking for a character?
CMPB R3,#^O15 ;Yes - end of line?
BNEQ 20$
10$: BRB XCTCHT ;Yes - return true (negated)
20$: CMPB R3,#^A" " ;No - space or tab?
BEQL 10$ ;Yes
CMPB R3,#9
BEQL 10$ ;Yes
BRB XCTCHF ;Otherwise return false
XCCHSS: CMPB R3,#^A" " ;Space?
BEQL XCCHE0 ;Yes - make sure it's not trailing
CMPB R3,#9 ;Tab?
BEQL XCCHE0 ;Yes
BRW XCTCHF ;No - return false
XCCHE0: MOVL R1,SAVEAC ;Save R1
PUSHAL XCTCHP ;Save restore-R1 address
BISL #1,R1 ;Look for non-end of line
XCTCHE: MOVL CHRPTR,R4 ;Get cursor pointer
10$: CMPB R3,#^O15 ;At end of line?
BNEQ 20$ ;No
BRW XCTCHT ;Yes - return true
20$: CMPB R3,#^A" " ;No - got a (maybe trailing) space?
BEQL 30$ ;Yes - skip it
CMPB R3,#9 ;How about a (maybe trailing) tab?
BEQL 30$
BRW XCTCHF ;No - return false
30$: MOVZBL (R4)+,R3 ;Yes - get next character
BEQL 30$ ;Ignore nulls
BRB 10$ ;Go check the real character
;Here at end of execute buffer - finish off or pop up a level
XCTDUN: MOVL XCTPSV,R1 ;Got a saved pointer?
BEQL XCTDN1 ;No - really done
MOVL XCTPSV,XCTPTR ;Make saved pointer active again
CLRL XCTPSV ;Zero the saved pointer
MOVL XCTASV,XCTACR ;Set up saved starting pointer
MOVL XCTISV,XCTITR ;Set up nominal saved iterations
MOVL XCTNSV,XCTNUM ;Set up saved iterations, too
BRW XCTGET ; and continue with them
XCTDN1: BBC #V_XBN,F1,10$ ;Did user push a special button?
BISL #M_FLG,F ;Yes - remember it
10$: MOVL XCTASV,R1 ;Get the saved starting pointer
CLRL XCTASV ;and clear it
TSTL R1 ;Is there one?
BEQL XCTDN2 ;No
MOVL #XBFNUM-1,R2 ;Yes - find its index
20$: CMPL R1,XCTADR[R2] ;Is this it?
BEQL 30$ ;Yes
SOBGEQ R2,20$ ;No - try next one
30$: MOVL R2,XCTACW ;Save index as the actual active buffer
XCTDN2: MOVC3 #SAVPML,SAVPRM,PARAMS ;Restore all parameters
MOVAB TYPBUF,R5 ;Restore the type buffer pointer
BICL #SWFLGS,F ;Restore previous flag settings
BICL3 #^C<SWFLGS>,SAVFGS,R1
BISL R1,F
BICL #SWFLGS2,F1 ;Restore previous F1 settings
BICL3 #^C<SWFLGS2>,SAVFGS+4,R1
BISL R1,F1
MOVL XCTINI,R1 ;Is there an initial pointer?
BEQL 10$
MOVL R1,XCTACR ;Yes - set it up as starting pointer
10$: CLRL XCTINI ;Clear initial pointer
BICL #M_ENT,F ;Don't allow the user to leave enter in effect
BBCC #V_FLG,F,20$ ;Did user push a special button?
JMP LOOP ;Yes - screen is already OK
20$: JMP DISALL ;No - re-display screen and loop
;Execute error messages
XSXERM: .ASCIZ /####Execute stacked too deeply/
XSXERR: MOVAB XSXERM,R1
CLRL XCTPSV
JMP ERROR
XSCERM: .ASCIZ /Counter must have a numeric parameter/
XSCERR: MOVAB XSCERM,R1
JMP ERROR
XWFERM: .ASCIZ /####Bad format for execute file/
XWFERR: MOVAB XWFERM,R1
JMP ERROR
XCIERM: .ASCIZ /#######Execute file not found/
XCIERR: MOVAB XCIERM,R1
JMP ERROR
XCXERM: .ASCIZ /######Current buffer is empty/
XCXERR: MOVAB XCXERM,R1
JMP ERROR
XCOERM: .ASCIZ /########No buffer is active/
XCOERR: MOVAB XCOERM,R1
JMP ERROR
XCSERM: .ASCIZ /#No free buffers - kill something/
XCSERR: MOVAB XCSERM,R1
JMP ERROR
XCEERM: .ASCIZ /####Start or end of file reached/
XCEERR::MOVAB XCEERM,R1
MOVAB TYPBUF,R5
JMP ERROR
XCKERM: .ASCIZ /####Can't kill - name not found/
XCKERR: MOVAB XCKERM,R1
JMP ERROR
XCTERM: .ASCIZ /Execute buffer is about to overflow/
XCTERR::CLRB @XCTPTW ;End buffer with a null
BICL #M_XSV,F1 ;Stop saving
MOVAB XCTERM,R1
JMP ERROR
XCVERM: .ASCIZ /#####Execute buffer overflowed/
XCVERR: MOVL XCTACW,R1 ;Clear overflowed buffer
MOVL XCTADR[R1],R1
CLRL (R1)
MOVAB XCVERM,R1
JMP ERROR
XABERM: .ASCIZ /#########Execution stopped/
XABERR: MOVAB XABERM,R1
JMP ERROR
GLOB ;Define the global symbols
.END