home *** CD-ROM | disk | FTP | other *** search
- ; Clip input lines on specified locations and write result to standard output.
-
- INCLUDE "/include/init.i"
-
- ; OPT D+
-
- ; Local Equs
-
- MaxLineSize EQU 512
-
- ; Variable storage
-
- STRUCT ArgArray,(4+1)*4
- LONG StdIn
- LONG StdOut
- LONG ByteFetch
- LONG ReadBytesLeft
- LONG Count1
- LONG Count2
- LONG Delta1
- LONG Delta2
- LONG ID1StrPtr
- LONG ID2StrPtr
- LONG ID1Exclusive
- LONG ID2Exclusive
- SIZE
-
- ; Regs
-
-
- Delta EQUR D4
- Count EQUR D5
- LineBufPtr EQUR D6
- LineBufLeft EQUR D7
- LineEndPtr EQUR A2
- IDStrPtr EQUR A3
- ErrorStrPtr EQUR A4
-
- ; Startup
-
- STACK 4000
- INIT
-
- ; Let ARP interpret the commandline
-
- MOVE.L ComLineBase(GP),A0
- MOVE.L ComLineSize(GP),D0
- LEA HelpMsg(PC),A1
- LEA ArgArray(GP),A2
- LEA Template(PC),A3
- MOVE.L A1,(A2)
- CALL GADS
- MOVE.L (A2),ErrorStrPtr
- TST.L D0
- BEQ ErrorExit
- BMI ErrorExit
-
- ; Interpret the count values
-
- MOVE.L ArgArray+0*4(GP),A0
- BSR GetSignedNum
- BEQ ErrorExit
- MOVE.L D0,Count1(GP)
- MOVE.L D1,Delta1(GP)
-
- MOVE.L ArgArray+2*4(GP),A0
- BSR GetSignedNum
- BEQ ErrorExit
- MOVE.L D0,Count2(GP)
- MOVE.L D1,Delta2(GP)
-
- ; Interpret the ID strings
-
- LEA EmptyString(PC),A1
-
- MOVE.L ArgArray+1*4(GP),D0
- BNE.S ID1StringSpecified
- MOVE.L A1,D0
- ID1StringSpecified:
- MOVE.L D0,A0
-
- CMP.B #'x',(A0)
- BNE.S NoID1Exclusion
- ADDQ.L #1,A0
- ADDQ.L #1,ID1Exclusive(GP)
- NoID1Exclusion:
- MOVE.L A0,ID1StrPtr(GP)
-
- MOVE.L ArgArray+3*4(GP),D0
- BNE.S ID2StringSpecified
- MOVE.L A1,D0
- ID2StringSpecified:
- MOVE.L D0,A0
-
- CMP.B #'x',(A0)
- BNE.S NoID2Exclusion
- ADDQ.L #1,A0
- ADDQ.L #1,ID2Exclusive(GP)
- NoID2Exclusion:
- MOVE.L A0,ID2StrPtr(GP)
-
- ; Open the standard input & output
-
- CALL Input
- MOVE.L D0,StdIn(GP)
- CALL Output
- MOVE.L D0,StdOut(GP)
-
- ; Allocate the read-line buffer
-
- LEA OutOfMem(PC),ErrorStrPtr
- MOVE.L #MaxLineSize+4+MaxLineSize,D0 ; 2 part buf with 0 term space.
- MOVEQ #0,D1
- CALL ArpAllocMem
- MOVE.L D0,LineBufPtr
- BEQ ErrorExit
-
-
- ; ** This is an intelligent ReadLine routine.
-
- ; Reinitialize the line buffer. (First part of dual buffer space)
-
- DoForEachLine:
- LEA ReadError(PC),ErrorStrPtr
- MOVE.L LineBufPtr,LineEndPtr
- MOVE.L #MaxLineSize,LineBufLeft
-
- ; Extract lines from the readbuffer into the line buffer.
-
- BRA.S ExtractEntry
- CopyLineBytes:
- MOVE.L ByteFetch(GP),A0
- ADDQ.L #1,ByteFetch(GP)
- SUBQ.L #1,ReadBytesLeft(GP)
- MOVE.B (A0),D0
- CMP.B #10,D0
- BEQ.S GotLine
- MOVE.B D0,(LineEndPtr)+
- SUBQ.L #1,LineBufLeft
- BEQ.S GotLine
- ExtractEntry:
- TST.L ReadBytesLeft(GP) ; Stack vars 0 init
- BNE CopyLineBytes
-
- ; Refill the read buffer.
-
- MOVE.L StdIn(GP),D1
- MOVE.L LineBufPtr,D2
- MOVE.L #MaxLineSize,D3
- ADD.L D3,D2
- ADDQ.L #4,D2
- CALL Read
- TST.L D0
- BMI ErrorExit
- BNE.S NotYetDone
- CMP.L LineBufPtr,LineEndPtr
- BEQ.S Exit
- NotYetDone:
- MOVE.L D2,ByteFetch(GP)
- MOVE.L D0,ReadBytesLeft(GP)
- BNE CopyLineBytes
-
- ; Adjust end of line pointer and weed out empty lines
-
- GotLine:
- SUBQ.L #1,LineEndPtr
- CMP.L LineBufPtr,LineEndPtr
- BLO DoForEachLine
-
- ; Find the initial clip postition
-
- MOVE.L LineBufPtr,A0
- MOVE.L Delta1(GP),Delta
- BPL.S InitialPosSet
- MOVE.L LineEndPtr,A0
- InitialPosSet:
- MOVE.L Count1(GP),Count
- MOVE.L ID1StrPtr(GP),IDStrPtr
- BSR.S FindClipPosition
- BNE DoForEachLine
- MOVE.L A0,D3
-
- ; Find the secondary clip postition.
-
- MOVE.L Delta2(GP),Delta
- MOVE.L Count2(GP),Count
- MOVE.L ID2StrPtr(GP),IDStrPtr
- BSR.S FindClipPosition
- BNE DoForEachLine
-
- ; Adjust for direction, adjust for exclusion and compute the length.
-
- MOVE.L ID1Exclusive(GP),D0
- MOVE.L ID2Exclusive(GP),D1
- CMP.L A0,D3
- BHI.S InvertedDirection
- EXG D0,D1
- EXG A0,D3
- InvertedDirection:
- ADD.L D1,A0
- SUB.L D0,D3
- SUB.L A0,D3
- BMI DoForEachLine
- ADDQ.L #2,D3
-
- ; Terminate with a LF and write the line clip.
-
- LEA WriteError(PC),ErrorStrPtr
- MOVE.B #10,-1(A0,D3.L)
- MOVE.L StdOut(GP),D1
- MOVE.L A0,D2
- CALL Write
- CMP.L D0,D3
- BNE.S ErrorExit
- WriteDone:
-
- ; Check if user hit ^C
-
- SkipWrite:
- SUB.L A1,A1
- CALL CheckAbort
- MOVE.L A1,ErrorStrPtr
- TST.L D0
- BNE.S ErrorExit
- BRA DoForEachLine
-
- ; Done, cleanup
-
- Exit:
- CLR.W ReturnCode(GP)
- SUB.L ErrorStrPtr,ErrorStrPtr
- ErrorExit:
-
- ; Display error string, if any, and exit
-
- MOVE.L ErrorStrPtr,D0
- BEQ.S NoErrorMsg
- MOVE.L D0,A1
- CALL Puts
- NoErrorMsg:
- RTS
-
- ; Subroutines
-
- ; This subroutine tried to find the CNTth position in the current line (relative
- ; to the initial position) which matches the ID string.
- ; I : A0 = Initial search position
- ; O : A0 = Clip position
- ; : Z=1 if search succeeded.
- ; : LineBufPtr,LineEndPtr,Delta,Count,IDStrPtr should be initialized
-
- FindClipPosition:
-
- ; Set the boundary to check with in D0 (Given position movement direction)
-
- MOVE.L LineBufPtr,D0
- TST.L Delta
- BMI.S FetchedRelevantBoundary
- MOVE.L LineEndPtr,D0
- FetchedRelevantBoundary:
-
- ; Check if all matches found or boundary reached. If not move current position.
-
- TST.L Count
- CheckNextByte:
- BEQ.S GotClipPosition
- NoByteMatch:
- CMP.L D0,A0
- BEQ.S AtLineBoundary
- ADD.L Delta,A0
-
- ; Check byte on the current position matched the ID string.
-
- TST.B (IDStrPtr)
- BEQ.S ByteMatched
- MOVE.L IDStrPtr,A1
- MOVE.B (A0),D1
- TryToMatchNextByte:
- CMP.B (A1)+,D1
- BEQ.S ByteMatched
- TST.B (A1)
- BEQ NoByteMatch
- BRA TryToMatchNextByte
- ByteMatched:
- SUBQ.L #1,Count
- BRA CheckNextByte
-
- ; Done. Take care of the Z-flag.
-
- AtLineBoundary:
- TST.B (IDStrPtr)
- GotClipPosition:
- RTS
-
- ; This sub decodes an ASCII buffer containing a signed number to a positive
- ; number and a sign boolean. It also sets ErrorStrPtr to "Invalid count"
- ; I : A0 = Ptr ASCII buffer
- ; O : D0.L = Integer >= 0
- ; : D1.L = +1 if positive, -1 if negative
- ; : Z = 1 if error
-
- GetSignedNum:
- LEA InvalidCnt(PC),ErrorStrPtr
- MOVEQ #-1,D1
- CMP.B #'-',(A0)+
- BEQ.S ConvertToLong
- MOVEQ #+1,D1
- CMP.B #'+',-(A0)
- BNE.S ConvertToLong
- ADDQ.L #1,A0
- ConvertToLong:
- MOVE.L D1,-(SP)
- CALL Atol
- MOVEM.L (SP)+,D1
- RTS
-
- ; The string section
-
- Template:
- DC.B 'CNT1/a,ID1/k,CNT2/a,ID2/k',0
- HelpMsg:
- DC.B 'Clip - Pipe through clipped lines.',10
- DC.B 'Usage: Clip <Cnt1> [ID1 [x]"charlist"] <RelCnt2> [ID2 [x]"charlist"]',0
- OutOfMem:
- DC.B 'Out of memory!',0
- InvalidCnt:
- DC.B 'Invalid count',0
- ReadError:
- DC.B 'Error while reading',0
- WriteError:
- DC.B 'Error while writing',0
- EmptyString:
- DC.B 0
- CNOP 0,2
-
- END
-