home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / misc / tinytools.lzh / CLIP / CLIP.ASM next >
Encoding:
Assembly Source File  |  1990-10-10  |  6.0 KB  |  337 lines

  1. ; Clip input lines on specified locations and write result to standard output.
  2.  
  3.     INCLUDE    "/include/init.i"
  4.  
  5. ;    OPT    D+
  6.  
  7. ; Local Equs
  8.  
  9. MaxLineSize    EQU    512
  10.  
  11. ; Variable storage
  12.  
  13.     STRUCT    ArgArray,(4+1)*4
  14.     LONG    StdIn
  15.     LONG    StdOut
  16.     LONG    ByteFetch
  17.     LONG    ReadBytesLeft
  18.     LONG    Count1
  19.     LONG    Count2
  20.     LONG    Delta1
  21.     LONG    Delta2
  22.     LONG    ID1StrPtr
  23.     LONG    ID2StrPtr
  24.     LONG    ID1Exclusive
  25.     LONG    ID2Exclusive
  26.     SIZE
  27.  
  28. ; Regs
  29.  
  30.  
  31. Delta        EQUR    D4
  32. Count        EQUR    D5
  33. LineBufPtr    EQUR    D6
  34. LineBufLeft    EQUR    D7
  35. LineEndPtr    EQUR    A2
  36. IDStrPtr    EQUR    A3
  37. ErrorStrPtr    EQUR    A4
  38.  
  39. ; Startup
  40.  
  41.     STACK    4000
  42.     INIT
  43.  
  44. ; Let ARP interpret the commandline
  45.  
  46.     MOVE.L    ComLineBase(GP),A0
  47.     MOVE.L    ComLineSize(GP),D0
  48.     LEA    HelpMsg(PC),A1
  49.     LEA    ArgArray(GP),A2
  50.     LEA    Template(PC),A3
  51.     MOVE.L    A1,(A2)
  52.     CALL    GADS
  53.     MOVE.L    (A2),ErrorStrPtr
  54.     TST.L    D0
  55.     BEQ    ErrorExit
  56.     BMI    ErrorExit
  57.  
  58. ; Interpret the count values
  59.  
  60.     MOVE.L    ArgArray+0*4(GP),A0
  61.     BSR    GetSignedNum
  62.     BEQ    ErrorExit
  63.     MOVE.L    D0,Count1(GP)
  64.     MOVE.L    D1,Delta1(GP)
  65.  
  66.     MOVE.L    ArgArray+2*4(GP),A0
  67.     BSR    GetSignedNum
  68.     BEQ    ErrorExit
  69.     MOVE.L    D0,Count2(GP)
  70.     MOVE.L    D1,Delta2(GP)
  71.  
  72. ; Interpret the ID strings
  73.  
  74.     LEA    EmptyString(PC),A1
  75.  
  76.     MOVE.L    ArgArray+1*4(GP),D0
  77.     BNE.S    ID1StringSpecified
  78.     MOVE.L    A1,D0
  79. ID1StringSpecified:
  80.     MOVE.L    D0,A0
  81.  
  82.     CMP.B    #'x',(A0)
  83.     BNE.S    NoID1Exclusion
  84.     ADDQ.L    #1,A0
  85.     ADDQ.L    #1,ID1Exclusive(GP)
  86. NoID1Exclusion:
  87.     MOVE.L    A0,ID1StrPtr(GP)
  88.  
  89.     MOVE.L    ArgArray+3*4(GP),D0
  90.     BNE.S    ID2StringSpecified
  91.     MOVE.L    A1,D0
  92. ID2StringSpecified:
  93.     MOVE.L    D0,A0
  94.  
  95.     CMP.B    #'x',(A0)
  96.     BNE.S    NoID2Exclusion
  97.     ADDQ.L    #1,A0
  98.     ADDQ.L    #1,ID2Exclusive(GP)
  99. NoID2Exclusion:
  100.     MOVE.L    A0,ID2StrPtr(GP)
  101.  
  102. ; Open the standard input & output
  103.  
  104.     CALL    Input
  105.     MOVE.L    D0,StdIn(GP)
  106.     CALL    Output
  107.     MOVE.L    D0,StdOut(GP)
  108.  
  109. ; Allocate the read-line buffer
  110.  
  111.     LEA    OutOfMem(PC),ErrorStrPtr
  112.     MOVE.L    #MaxLineSize+4+MaxLineSize,D0    ; 2 part buf with 0 term space.
  113.     MOVEQ    #0,D1
  114.     CALL    ArpAllocMem
  115.     MOVE.L    D0,LineBufPtr
  116.     BEQ    ErrorExit
  117.  
  118.  
  119. ; ** This is an intelligent ReadLine routine.
  120.  
  121. ; Reinitialize the line buffer. (First part of dual buffer space)
  122.  
  123. DoForEachLine:
  124.     LEA    ReadError(PC),ErrorStrPtr
  125.     MOVE.L    LineBufPtr,LineEndPtr
  126.     MOVE.L    #MaxLineSize,LineBufLeft
  127.  
  128. ; Extract lines from the readbuffer into the line buffer.
  129.  
  130.     BRA.S    ExtractEntry
  131. CopyLineBytes:
  132.     MOVE.L    ByteFetch(GP),A0
  133.     ADDQ.L    #1,ByteFetch(GP)
  134.     SUBQ.L    #1,ReadBytesLeft(GP)
  135.     MOVE.B    (A0),D0
  136.     CMP.B    #10,D0
  137.     BEQ.S    GotLine
  138.     MOVE.B    D0,(LineEndPtr)+
  139.     SUBQ.L    #1,LineBufLeft
  140.     BEQ.S    GotLine
  141. ExtractEntry:
  142.     TST.L    ReadBytesLeft(GP)        ; Stack vars 0 init
  143.     BNE    CopyLineBytes
  144.  
  145. ; Refill the read buffer.
  146.  
  147.     MOVE.L    StdIn(GP),D1
  148.     MOVE.L    LineBufPtr,D2
  149.     MOVE.L    #MaxLineSize,D3
  150.     ADD.L    D3,D2
  151.     ADDQ.L    #4,D2
  152.     CALL    Read
  153.     TST.L    D0
  154.     BMI    ErrorExit
  155.     BNE.S    NotYetDone
  156.     CMP.L    LineBufPtr,LineEndPtr
  157.     BEQ.S    Exit
  158. NotYetDone:
  159.     MOVE.L    D2,ByteFetch(GP)
  160.     MOVE.L    D0,ReadBytesLeft(GP)
  161.     BNE    CopyLineBytes
  162.  
  163. ; Adjust end of line pointer and weed out empty lines
  164.  
  165. GotLine:
  166.     SUBQ.L    #1,LineEndPtr
  167.     CMP.L    LineBufPtr,LineEndPtr
  168.     BLO    DoForEachLine
  169.  
  170. ; Find the initial clip postition
  171.  
  172.     MOVE.L    LineBufPtr,A0
  173.     MOVE.L    Delta1(GP),Delta
  174.     BPL.S    InitialPosSet
  175.     MOVE.L    LineEndPtr,A0
  176. InitialPosSet:
  177.     MOVE.L    Count1(GP),Count
  178.     MOVE.L    ID1StrPtr(GP),IDStrPtr    
  179.     BSR.S    FindClipPosition
  180.     BNE    DoForEachLine
  181.     MOVE.L    A0,D3
  182.  
  183. ; Find the secondary clip postition.
  184.  
  185.     MOVE.L    Delta2(GP),Delta
  186.     MOVE.L    Count2(GP),Count
  187.     MOVE.L    ID2StrPtr(GP),IDStrPtr
  188.     BSR.S    FindClipPosition
  189.     BNE    DoForEachLine
  190.  
  191. ; Adjust for direction, adjust for exclusion and compute the length.
  192.  
  193.     MOVE.L    ID1Exclusive(GP),D0
  194.     MOVE.L    ID2Exclusive(GP),D1
  195.     CMP.L    A0,D3
  196.     BHI.S    InvertedDirection
  197.     EXG    D0,D1
  198.     EXG    A0,D3
  199. InvertedDirection:
  200.     ADD.L    D1,A0
  201.     SUB.L    D0,D3
  202.     SUB.L    A0,D3
  203.     BMI    DoForEachLine
  204.     ADDQ.L    #2,D3
  205.  
  206. ; Terminate with a LF and write the line clip.
  207.  
  208.     LEA    WriteError(PC),ErrorStrPtr
  209.     MOVE.B    #10,-1(A0,D3.L)
  210.     MOVE.L    StdOut(GP),D1
  211.     MOVE.L    A0,D2
  212.     CALL    Write
  213.     CMP.L    D0,D3
  214.     BNE.S    ErrorExit
  215. WriteDone:
  216.  
  217. ; Check if user hit ^C 
  218.  
  219. SkipWrite:
  220.     SUB.L    A1,A1
  221.     CALL    CheckAbort
  222.     MOVE.L    A1,ErrorStrPtr
  223.     TST.L    D0
  224.     BNE.S    ErrorExit
  225.     BRA    DoForEachLine
  226.  
  227. ; Done, cleanup
  228.  
  229. Exit:
  230.     CLR.W    ReturnCode(GP)
  231.     SUB.L    ErrorStrPtr,ErrorStrPtr
  232. ErrorExit:
  233.  
  234. ; Display error string, if any, and exit
  235.  
  236.     MOVE.L    ErrorStrPtr,D0
  237.     BEQ.S    NoErrorMsg
  238.     MOVE.L    D0,A1
  239.     CALL    Puts
  240. NoErrorMsg:
  241.     RTS
  242.  
  243. ; Subroutines
  244.  
  245. ; This subroutine tried to find the CNTth position in the current line (relative
  246. ; to the initial position) which matches the ID string.
  247. ; I : A0 = Initial search position
  248. ; O : A0 = Clip position
  249. ;   : Z=1 if search succeeded.
  250. ;   : LineBufPtr,LineEndPtr,Delta,Count,IDStrPtr should be initialized
  251.  
  252. FindClipPosition:
  253.  
  254. ; Set the boundary to check with in D0 (Given position movement direction)
  255.  
  256.     MOVE.L    LineBufPtr,D0
  257.     TST.L    Delta
  258.     BMI.S    FetchedRelevantBoundary
  259.     MOVE.L    LineEndPtr,D0
  260. FetchedRelevantBoundary:
  261.  
  262. ; Check if all matches found or boundary reached. If not move current position.
  263.  
  264.     TST.L    Count
  265. CheckNextByte:
  266.     BEQ.S    GotClipPosition
  267. NoByteMatch:
  268.     CMP.L    D0,A0
  269.     BEQ.S    AtLineBoundary
  270.     ADD.L    Delta,A0
  271.  
  272. ; Check byte on the current position matched the ID string.
  273.  
  274.     TST.B    (IDStrPtr)
  275.     BEQ.S    ByteMatched
  276.     MOVE.L    IDStrPtr,A1
  277.     MOVE.B    (A0),D1
  278. TryToMatchNextByte:
  279.     CMP.B    (A1)+,D1
  280.     BEQ.S    ByteMatched
  281.     TST.B    (A1)
  282.     BEQ    NoByteMatch
  283.     BRA    TryToMatchNextByte
  284. ByteMatched:
  285.     SUBQ.L    #1,Count
  286.     BRA    CheckNextByte
  287.  
  288. ; Done. Take care of the Z-flag.
  289.  
  290. AtLineBoundary:
  291.     TST.B    (IDStrPtr)
  292. GotClipPosition:
  293.     RTS
  294.  
  295. ; This sub decodes an ASCII buffer containing a signed number to a positive
  296. ; number and a sign boolean. It also sets ErrorStrPtr to "Invalid count"
  297. ; I : A0 = Ptr ASCII buffer
  298. ; O : D0.L = Integer >= 0
  299. ;   : D1.L = +1 if positive, -1 if negative
  300. ;   : Z = 1 if error
  301.  
  302. GetSignedNum:
  303.     LEA    InvalidCnt(PC),ErrorStrPtr
  304.     MOVEQ    #-1,D1
  305.     CMP.B    #'-',(A0)+
  306.     BEQ.S    ConvertToLong
  307.     MOVEQ    #+1,D1
  308.     CMP.B    #'+',-(A0)
  309.     BNE.S    ConvertToLong
  310.     ADDQ.L    #1,A0
  311. ConvertToLong:
  312.     MOVE.L    D1,-(SP)
  313.     CALL    Atol
  314.     MOVEM.L    (SP)+,D1
  315.     RTS
  316.  
  317. ; The string section
  318.  
  319. Template:
  320.     DC.B    'CNT1/a,ID1/k,CNT2/a,ID2/k',0
  321. HelpMsg:
  322.     DC.B    'Clip - Pipe through clipped lines.',10
  323.     DC.B    'Usage: Clip <Cnt1> [ID1 [x]"charlist"] <RelCnt2> [ID2 [x]"charlist"]',0
  324. OutOfMem:
  325.     DC.B    'Out of memory!',0
  326. InvalidCnt:
  327.     DC.B    'Invalid count',0
  328. ReadError:
  329.     DC.B    'Error while reading',0
  330. WriteError:
  331.     DC.B    'Error while writing',0
  332. EmptyString:
  333.     DC.B    0
  334.     CNOP    0,2
  335.  
  336.     END
  337.