.Title Span Characters in a Structure .Psect Alvin,Gbl,Con .Ident /LVL51 / .Mcall $Alvin $Alvin ;+ ;;********************************************************************** ;; Subroutine to SPAN CONTROL CHARACTERS or SEARCH for a character ;; in an Alvin buffer, string, or command string. A SSTR is presumed ;; to be a static string descriptor which implies NOUPDATE & RETURN. ;; A CSTR is a command string and allows updating the dynamic ;; BEGIN pointer. Both string descriptors are processed from the ;; BEGIN pointer to the END pointer. A BUFFER is processed from ;; the OUTPUT pointer to the INPUT pointer with the output pointer ;; being updated according to the function parameters. ;; ;; By default (FUNCTION=0) the structure is searched for the first ;; occurance of a non-CONTROL character and the descriptor is ;; updated (except a static string is never updated). ;; If a character is specified with such a zero function, this ;; character also will be spanned if it occurs. If the "NOT" function ;; is specified, this character will not be spanned, ;; (ie. NOT+CR = Do not span carriage return(s)). If the ;; "UNTIL" function is specified, all characters will be spanned ;; until this character is found. If the "ONLY" function is ;; specified, only occurances of the specified character will be ;; spanned. these functions should be treated as being mutually ;; exclusive. ;; ;; The function "RETURN" can be used to return the final ;; pointer value in register 0. The "NOUPDATE" function can be ;; used to explicitly avoid updating the descriptor. Therefore ;; "NOUPDATE" + "RETURN" will return the determined position ;; (pointer value) to the calling routine but will not update the ;; descriptor; this is the case for all SSTR (static string) calls. ;; ;; PARITY bits are removed before the characters are compared. ;; If the structure at any time is found to be empty, the EMPTY EXIT ;; will be taken. Note that the empty condition can give ;; information about the success of the selected span function ;; or its inverse. ;; ;; Expects calls of the form: ;; ;; JSR R5,SPAN ;; .WORD (descriptor address) ;; .WORD (FUNCTION)+(CHARACTER) ;; BR (empty exit) ;; ;; ;; Note: If the DESCRIPTOR ADDRESS is ZERO, Then this address is ;; assumed to already be in register 4. ;; ;; Function Bit Definitions (can be defined with the $SPAN macro): ;; NOT=100000 ;Function for not skipping specified control character. ONLY=40000 ;Function for only skipping specified character. UNTIL=20000 ;Function for skipping until the specified character. RETURN=10000 ;Function for returning new pointer in register 0. NOUPDATE=4000 ;Function for not updating descriptor with new pointer. SSTR=2000 ;Specifies a Static String, implies RETURN & NOUPDATE. CSTR=1000 ;Specifies a Command String. Command String is also detected ; if the Descriptor START & END values indicate such: ; ; A Buffer Descriptor: Input ptr A Command Desc: Dynamic Begin ptr ; Output ptr Dynamic End ptr ; Start ptr (static) End ptr (static) ; End ptr (static) Start ptr (static) ; ; A Static String: Begin ptr (address of first character in the string) ; End ptr (address of last character in the string) ;- SPAN:: MOV R4,-(SP) ;SAVE REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV (R5)+,R3 ;GET THE BUFFER DESCRIPTOR ADDRESS BEQ SPANGO ;IF ZERO, BUF DESC ADR IS ALREADY IN REG 4 MOV R3,R4 ;PUT BUF DESC ADR IN REG 4 SPANGO: MOV (R5)+,R1 ;GET THE FUNCTION AND CHARACTER PARAMETERS BIC #200,R1 ;CLEAR CHARACTER PARAMETER PARITY BIT Bit #SSTR!CSTR,R1 ;Did the user request STRING processing? Bne SpanST ;Yes, branch Mov Bout(R4),R2 ;Get output ptr - presuming buffer desc. Cmp Bstart(R4),Bend(R4) ;Is this a buffer or a command string? Blo SpanB ;Branch if its a buffer. Bis #CSTR,R1 ;Else process as a command string. SpanST: Mov (R4)+,R2 ;Get the string Begin pointer, incr R4 to End ptr SpanSL: Cmp R2,(R4) ;Are there characters yet in the string? Bhi SpanEmpty ;No, branch to finish. SpanCo: MOVB (R2),R3 ;GET THE NEXT BYTE IN THE BUFFER BIC #200,R3 ;CLEAR THE PARITY BIT CMPB R1,R3 ;CHARACTERS EQUAL? BNE SPANIF ;NO, BRANCH BIT #UNTIL!NOT,R1 ;Should this char be skipped? BNE SPANEXIT ;No, exit. SPANIT: INC R2 ;Increment temporary work pointer. Bit #SStr!CStr,R1 ;Is this a string? Bne SpanSL ;Yes, test end-of-string. CMP R2,Bend(R4) ;Need to wrap-around - @end of the buffer? BLOS SPANB ;No, loop MOV BStart(R4),R2 ;Yes, wrap-around to start of buffer. SpanB: CMP (R4),R2 ;Is INPUT PTR=OUTPUT PTR of buffer? BEQ SPANEMPTY ;Yes, then take the BUFFER EMPTY exit. Br SpanCommon ;Proceed to check next character ;; SPANIF: BIT #UNTIL,R1 ;CHARS ARE NOT EQUAL BNE SPANIT ;SPAN UNTIL A MATCH IS FOUND BIT #ONLY,R1 ;EXPLICITLY SPAN ONLY THE SPECIFIED CHAR? BNE SPANEXIT ;EXIT BECAUSE THEY ARE DIFFERENT CMPB #40,R3 ;IS THIS A CONTROL CHAR? BPL SPANIT ;YES, REMOVE IT FROM THE BUFFER SPANEXIT: TST (R5)+ ;INCR PAST BUFFER EMPTY EXIT SPANEMPTY: BIT #RETURN!SStr,R1 ;Should new pointer be returned? BEQ SPANUP ;No, proceed to check update MOV R2,R0 ;Yes, return it in reg 0. SPANUP: BIT #NOUPDATE!SStr,R1 ;Should the descriptor be updated? BNE SPANOUT ;No, branch. Bit #CStr,R1 ;Update a command or buffer descriptor? Beq SpanUB ;Branch to update the buffer descriptor. Mov R2,-(R4) ;Update the dynamic begin ptr of cmd desc. Br Spanout ; and exit. SpanUB: MOV R2,Bout(R4) ;Move new OUTPUT POINTER into the buffer desc. SPANOUT: MOV (SP)+,R1 ;Restore registers used MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;Return. ;;*********************************** .End