home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol167 / mkv86.a86 < prev    next >
Encoding:
Text File  |  1984-04-29  |  18.9 KB  |  624 lines

  1.  
  2. ;    =======================================================
  3. ;
  4. ;
  5. ;    Module composed of workspace operators for REC/MARKOV.
  6. ;    These are specialized subroutines for manipulating a
  7. ;    "workspace,"  which is an array together with five
  8. ;    pointers.  The workspace will probably (but not always)
  9. ;    hold text, subdivisions of which are marked off by the
  10. ;    pointers.  They in turn are:
  11. ;
  12. ;        p0  the beginning of both space and text
  13. ;        p1  the beginning of a specific segment
  14. ;        p2  the end of a specific segment
  15. ;        p3  the end of the entire text
  16. ;        p4  the physical end of the available space
  17. ;
  18. ;    The uniform method to designate intervals is that the
  19. ;    beginning is inclusive, while the end is exclusive.  In
  20. ;    that way a null interval can be represented through two
  21. ;    equal pointers.  The workspace operators and predicates
  22. ;    move data around and compare it with the help of these
  23. ;    pointers.  Other operators move data between the work-
  24. ;    space and the pushdown list.
  25. ;
  26. ;    The complete list of operators and predicates is:
  27. ;
  28. ;        A    advance pointer 1 if possible
  29. ;        B    retract pointer 1 if possible
  30. ;        D    delete interval between p1 and p2
  31. ;        E    test equality between workspace and PDL
  32. ;        F    find a specified segment in the workspace
  33. ;        I    insert in the workspacve following p2
  34. ;        J    move p1 to beginning
  35. ;        M    test workspace for lexicographically larger
  36. ;        Q    move interval between p1 and p2 to PDL
  37. ;        U    find segment between delimiters
  38. ;        V    find segment including delimiters
  39. ;        Y   restore pointer 1 to previous value
  40. ;        Z    move p2 to end
  41. ;        a    extend interval from p1 if possible
  42. ;        b    extend interval to p2 if possiblle
  43. ;        e    extend limit of text if possible
  44. ;        f    fill if space is available
  45. ;        h    fetch workspace header for PDL
  46. ;        j    null interval at front of segment
  47. ;        q    place p1, p2-p1 on PDL
  48. ;        w    store (or possibly exchange) workspace header
  49. ;        z    null interval at end of segment
  50. ;        <    restrict workspace to segment p1-p2
  51. ;        >    open workspace to previous span
  52. ;
  53. ;    Version released during the Summer School, 1980.
  54. ;
  55. ;          MKV86 - Copyright (C) 1980
  56. ;        Universidad Autonoma de Puebla
  57. ;             All Rights Reserved
  58. ;
  59. ;         [Harold V. McIntosh, 25 April 1982]
  60. ;
  61. ;    May 1, 1982 - M tests for an interval rather than making
  62. ;        a simple comparison.  <a,'',M> should be used
  63. ;        where <a,M> was formerly written.  In general,
  64. ;        <a,b,M> tests for a .LE. WS .LE. b and leaves
  65. ;        P1 and P2 surrounding such a segment.  Both a
  66. ;        and b are always lifted.
  67. ;    May 29, 1983 - h discontinued; use ''w instead
  68. ;    =======================================================
  69.  
  70. ;    =======================================================
  71. ;    Workspace subroutines for REC/MARKOV.
  72. ;    =======================================================
  73.  
  74. ;    (a)  Generate a segment of length n forward from p1 if
  75. ;    possible.  A predicate which, when FALSE, leaves the
  76. ;    deficit by which the segment could not be formed on the
  77. ;    pushdown list.
  78.  
  79. LCA:    call    CXLD        ;load n into (cx)
  80.     add    cx,P1
  81.     cmp    P3,cx
  82.     jb    LAF
  83.     mov    P2,cx
  84.     jmp    SKP        ;return with the value TRUE
  85. LAF:    sub    cx,P3
  86.     push    cx        ;argument to putw must be on 8080 stack
  87.     call    PUTW        ;record deficit
  88.     ret            ;FALSE return: <jmp putw> won't do
  89.  
  90. ;    (A)  Pointer 1 advances by one byte, if possible.
  91.  
  92. UCA:    mov    ax,P1        ;fetch pointer 1
  93.     inc    ax        ;advance by 1
  94.     cmp    P3,ax
  95.     jb    UAF        ;forget it, return FALSE if past limit
  96.     mov    P1,ax        ;we can safely store pointer 1
  97.     cmp    P2,ax        ;but it still must not pass pointer 2
  98.     jnb    UA2        ;but it still must not pass pointer 2
  99.     mov    P2,ax        ;if it did, pointer 2 = pointer 1
  100. UA2:    jmp    SKP        ;but in either event, return TRUE
  101. UAF:    ret
  102.  
  103. ;    (b)  Generate a segment of length n backward from p2,
  104. ;    if possible.
  105.  
  106. LCB:    call    CXLD        ;load top argument into (cx), erase it
  107.     mov    ax,P2        ;fetch pointer 2 into (HL)
  108.     sub    ax,cx        ;calculate difference
  109.     cmp    ax,P0
  110.     jb    LBF        ;low limit passed, abandon the attempt
  111.     mov    P1,ax        ;record it
  112.     jmp    SKP        ;generate TRUE return for the predicate
  113. LBF:    ret
  114.  
  115. ;    (B)  Pointer 1 retreats by one byte, if possible.
  116.  
  117. UCB:    mov    ax,P1        ;fetch pointer
  118.     dec    ax        ;move backwards one byte
  119.     cmp    ax,P0        ;
  120.     jb    UBF
  121.     mov    P1,ax        ;otherwise store new position
  122.     jmp    SKP        ;and return with value TRUE
  123. UBF:    ret            ;return false as NOP if passed
  124.  
  125. ;    (D) Delete text between pointers 1 and 2.
  126.  
  127. UCD:    mov    si,P2        ;fetch end of deleted text
  128.     mov    di,P1        ;fetch beginning of deleted text
  129.     cmp    si,di
  130.     jz    UD2        ;null interval to delete
  131.     mov    P2,di        ;after deletion, interval is null
  132.     mov    cx,P3
  133.     sub    cx,si        ;length of string to move
  134.     jz    UD1
  135.     cld
  136.     mov    ax,ds
  137.     mov    es,ax
  138.     repnz    movs    byte [di],[si]
  139. UD1:    mov    P3,di        ;destination limit is new end of text
  140. UD2:    ret
  141.  
  142. ;    (e)  Attempt to move pointer 3 forward. If insufficient
  143. ;    space remains, this predicate is false and places the
  144. ;    amount of remaining space [p4-p3] on the pushdown list.
  145. ;    If the extension is possible, P1 and P2 will surround it.
  146.  
  147. LCE:    call    CXLD        ;load argument into (cx), pop it
  148.     add    cx,P3
  149.     cmp    P4,cx
  150.     jb    LEF        ;skip if increment not greater
  151.     mov    ax,P3
  152.     mov    P2,cx
  153.     mov    P3,cx
  154.     mov    P1,ax        ;make it the beginning of new interval
  155.     jmp    SKP        ;TRUE return
  156. LEF:    sub    cx,P4
  157.     push    cx        ;putw requires argument on 8080 stack
  158.     call    PUTW        ;insert balance on pushdown list
  159.     ret            ;TRUE return: <jmp putw> won't work
  160.  
  161. ;    (E) Check equality between the pushdown list and the
  162. ;    workspace.  The top argument will be erased whatever
  163. ;    the outcome of the test, a characteristic common to
  164. ;    E, F, M, U, and V.  If there is a segment originating
  165. ;    at p1 which is equal to the argument, p2 will move to
  166. ;    delimit it, otherwise p2 remains unchanged.
  167.  
  168. UCE:    mov    cx,PY        ;end of top argument
  169.     mov    si,PX        ;beginning of top argument
  170.     mov    di,P1        ;beginning of workspace segment in (HL)
  171.     sub    cx,si
  172.     jcxz    UEN        ;''E is TRUE, sets P2=P1
  173.     cld
  174.     mov    ax,ds
  175.     mov    es,ax
  176.     repz    cmps    byte [di],[si]
  177.     jnz    UEF        ;mismatch terminated scan
  178.     cmp    P3,di        ;see whether we've run over
  179.     jb    UEF
  180. UEN:    mov    P2,di
  181.     jmp    CUCL        ;skip for TRUE
  182. UEF:    jmp    UCL        ;FALSE for one reason or another
  183.  
  184. ;    (f)  Fill. <'XXX' f> will replace the text following
  185. ;    pointer 1 by XXX if pointer 2 does not conflict,
  186. ;    whereupon pointers 1 and 2 delimit what remains of
  187. ;    the interval they originally encompassed, making this
  188. ;    predicate TRUE.  Otherwise it will be FALSE, with the
  189. ;    pointers unaltered.  When f fails, its argument is
  190. ;    erased, otherwise the insert is conserved for repeated
  191. ;    use in a block fill.  f is true even if its argument
  192. ;    completely fills the available space, since it reports
  193. ;    whether or not an insertion took place rather than
  194. ;    whether any space remains.
  195.  
  196. LCF:    mov    si,PX
  197.     mov    cx,PY
  198.     sub    cx,si
  199.     mov    di,P1        ;load p2
  200.     mov    dx,P2        ;now load p1
  201.     sub    dx,di
  202.     cmp    dx,cx        ;compare this to p2
  203.     jnb    LFT
  204.     jmp    UCL        ;insert too big, FALSE and erase insert
  205. LFT:    cld
  206.     mov    ax,ds
  207.     mov    es,ax
  208.     repnz    movs    byte [di],[si]
  209.     mov    P1,di        ;final destination location is new p1
  210.     jmp    SKP        ;keep insert, generate TRUE return
  211.  
  212. ;    (F)  Search for text.  The text in the workspace is
  213. ;    examined from left to right beginning at pointer 1 to
  214. ;    see if the object of comparison on the pushdown list
  215. ;    can be found.  If so, its replica in the workspace is
  216. ;    bracketed by pointers 1 and 2, while the model itself
  217. ;    is discarded.  Even if no replica is found, the model
  218. ;    is still discarded, but then the value is FALSE and the
  219. ;    pointers 1 and 2 retain their original sites.  Should
  220. ;    several replicas exist, only the first is taken; if
  221. ;    consecutive searches for the same object are made, the
  222. ;    same replica will be found repeatedly.  This permits
  223. ;    nested fragments of the same object to be found on
  224. ;    successive searches, but requires an intermediate
  225. ;    collapse of the interval p1-p2 in favor of p2 [say by
  226. ;    using ''I] to scan multiple occurrences of the same
  227. ;    object.
  228.  
  229. UCF:    mov    dx,PY
  230.     mov    bx,PX
  231.     mov    di,P1
  232.     sub    dx,bx        ;length of comparison object
  233.     jz    UFX        ;fast exit for null object
  234.     mov    cx,P3
  235.     sub    cx,di        ;length of search field
  236.     cmp    cx,dx
  237.     jb    UFF        ;useless to even try
  238.     cld            ;searches go forward
  239.     mov    ax,ds
  240.     mov    es,ax        ;CP/M might derange ES
  241.     dec    dx
  242.     jz    UFS        ;look for single byte
  243. UF1:    mov    si,bx
  244.     lods    byte [si]
  245.     repnz    scas    byte [di]            ;search by increment until limit
  246.     jnz    UFF        ;end without even 1st word
  247.     cmp    cx,dx        ;are there enough chars left
  248.     jb    UFF        ;can't possibly fit it in
  249.     push    cx
  250.     push    di
  251.     mov    cx,dx
  252.     repz    cmps    byte [di],[si]
  253.     jz    UFT
  254.     pop    di        ;comparison failed
  255.     pop    cx
  256.     jmp    UF1        ;go on where we left off
  257. UFT:    pop    ax        ;comparison accomplished
  258.     pop    cx
  259. UFV:    dec    ax
  260.     mov    P1,ax
  261. UFX:    mov    p2,di
  262.     jmp    CUCL
  263. UFS:    mov    al,[bx]
  264.     repnz    scas    byte [di]
  265.     jnz    UFF
  266.     mov    ax,di
  267.     jmp    UFV
  268. UFF:    jmp    UCL
  269.  
  270. ;    (I)  Insert text following pointer 2; upon completion
  271. ;    pointers bracket inserted material.  If the proposed
  272. ;    insertion will not fit, an error indicator is generated
  273. ;    and the attempt is abandoned.  An F followed by an I
  274. ;    will insert material after the found text, but if an
  275. ;    intermediate ''F is given, insertion will be made at
  276. ;    the front of the text.  A ''I may be used to form null
  277. ;    intervals, if they are desired at the end of a segment.
  278.  
  279. UCI:    mov    ax,P2        ;point where insertion will be made
  280.     mov    P1,ax        ;pointer 1 to precede inserted material
  281.     mov    dx,PY        ;source origin
  282.     sub    dx,PX        ;source end
  283.     jz    UIN        ;null insert
  284.     mov    si,P3
  285.     mov    cx,P4
  286.     sub    cx,si
  287.     cmp    cx,dx
  288.     jb    UIE        ;insufficient space for insert
  289.     mov    cx,si
  290.     sub    cx,P2
  291.     add    P2,dx
  292.     add    P3,dx
  293.     mov    ax,ds
  294.     mov    es,ax
  295.     jcxz    UIA
  296.     mov    di,P3
  297.     dec    si
  298.     dec    di
  299.     std
  300.     repnz    movs    byte [di],[si]
  301. UIA:    mov    cx,dx
  302.     mov    si,PX        ;source origin into (DE)
  303.     mov    di,P1        ;new p1 is destination origin, in (HL)
  304.     cld
  305.     repnz    movs    byte [di],[si]
  306. UIN:    jmp    UCL        ;I removes its argument upon completion
  307. UIE:    call    RER
  308.  
  309. ;    (j)  Null interval at p1.  Equivalent to ''F or ''E.
  310.  
  311. LCJ:    mov    ax,P1        ;pointer to beginning of interval
  312.     mov    P2,ax        ;make end of interval the same
  313.     ret
  314.  
  315. ;    (J) Back to beginning of workspace.  Extends whatsoever
  316. ;     interval back to the beginning of the entire text.
  317.  
  318. UCJ:    mov    ax,P0        ;fetch pointer to beginning of text
  319.     mov    P1,ax        ;make it the beginning of the interval
  320.     ret
  321.  
  322. ;    (M)  Compare inequality between the pushdown list and
  323. ;    the workspace.  M is TRUE if there is a segment in the
  324. ;    workspace beginning at p1 which is lexicographically
  325. ;    larger than the argument on the pushdown list.  In that
  326. ;    event, p2 marks the "larger" interval, which terminates
  327. ;    after the first byte in the workspace which is larger -
  328. ;    by unsigned integer comparison - than the argument.  M
  329. ;    is also TRUE if an equal segment lies in the workspace.
  330. ;    According to the common style of E, F, I, M, U, and V,
  331. ;    the argument is erased whatever might be the outcome of
  332. ;    the comparison.  Likewise, FALSE results in no pointer
  333. ;    changes.
  334.  
  335. UCM:    mov    cx,PY
  336.     mov    si,PX
  337.     sub    cx,si
  338.     push    cx
  339.     push    si
  340.     call    UCL
  341.     mov    cx,PY        ;pointer to argument to be compared
  342.     mov    si,PX        ;pointer to workspace under comparison
  343.     sub    cx,si
  344.     call    UCL
  345.     mov    bp,P1
  346.     jcxz    UMT        ;trivial comparison to be made
  347.     cld
  348.     mov    ax,ds
  349.     mov    es,ax
  350.     mov    di,bp
  351. UML:    cmps    byte [di],[si]            ;(SI) - (DI) sets flags
  352.     jb    UMM        ;decided if WS > PD
  353.     jnz    UMF        ;failure if WS < PD
  354.     loop    UML        ;repeat for WS = PD
  355. UMM:    xchg    di,bp
  356.     cmp    P3,bp
  357.     jb    UMF        ;fail if we run over
  358.     pop    si
  359.     pop    cx
  360.     jcxz    UMT        ;treat '' as 'no comparison'
  361.     mov    ax,cx
  362.     mov    cx,bp
  363.     sub    cx,di
  364.     cmp    ax,cx        ;set flags by l(PD) - l(WS)
  365.     sbb    dx,dx        ;(nc) when l(WS) .LE. l(PD)
  366.     jz    UMN        ;(z): workspace is shorter, equal
  367.     xchg    ax,cx        ;check only common segment
  368. UMN:    cmps    byte [di],[si]            ;set flags from PD - WS
  369.     jb    UMG        ;WS > PD means outside inclusive bound
  370.     jnz    UMT        ;WS < PD means bound is satisfied
  371.     loop    UMN        ;WS = PD means keep testing
  372.     or    dx,dx
  373.     jnz    UMG        ;(z): workspace fulfils 'short before long'
  374. UMT:    mov    P2,bp
  375.     jmp    SKP
  376. UMF:    add    sp,4
  377. UMG:    ret
  378.  
  379. ;    (q)  Put p1, p2-p1 on PDL.
  380.  
  381. LCQ:    mov    ax,P2
  382.     sub    ax,P1
  383.     push    ax        ;stash P2-P1 on 8086's PDK
  384.     push    P1        ;and then P1 on top of that
  385.     call    PUTW        ;one argument from top of 8080 stack
  386.     call    PUTW        ;then another so we've got both
  387.     ret            ;cannot use jmp putw for call putw, ret
  388.  
  389. ;    (Q)  Copy workspace to pushdown.  The interval between
  390. ;    p1 and p2 is placed on the pushdown list.
  391.  
  392. UCQ:    mov    si,P1        ;fetch beginning of interval
  393.     mov    cx,P2        ;fetch end of interval
  394.     sub    cx,si        ;length of interval into (cx)
  395.     call    NARG        ;close old arg, check space, def new
  396.     mov    di,PX        ;fetch destination origin for (HL)
  397.     cld
  398.     mov    ax,ds
  399.     mov    es,ax
  400.     repnz    movs    byte [di],[si]
  401.     mov    PY,di        ;destination end is argument end
  402.     ret
  403.  
  404. ;    (w)  Store workspace header.  There are two forms of
  405. ;    this operator which are available: the argument may be
  406. ;    either a single block of ten bytes, or else the pair
  407. ;    <org, siz>.  The distinction is implicit, according to
  408. ;    whether the top argument has two bytes or ten bytes.
  409. ;    The first case arises from a previous usage of h (or
  410. ;    perhaps deliberate construction), while the second is
  411. ;    more likely in the initial allocation of a workspace. A
  412. ;    single block is erased after use, while it is supposed
  413. ;    that a previous definition existed when the pair form
  414. ;    is used.  In such a case, the old block of bytes would
  415. ;    be substituted for the two arguments in case it needed
  416. ;    to be restored later.  When a workspace is generated
  417. ;    from its specifications, pointers 1 and 2 as well as 3
  418. ;    are set to encompass the entire space. Many other forms
  419. ;    can be arranged by a subsequent use of j, D, and so on.
  420.  
  421. LCW:    mov    si,PX
  422.     mov    cx,PY
  423.     sub    cx,si        ;determine size of argument
  424.     cmp    cx,10        ;ten for comparison
  425.     jnz    LWW        ;if length not 10, suppose it was 2
  426.     cmp    cx,0
  427.     jnz    LWX
  428.     call    UCL
  429. LWH:    mov    cx,10        ;10 bytes required from PDL
  430.     call    NARG        ;verify space, new px into (HL)
  431.     mov    si,(offset P0)        ;source is pointer block itself
  432.     cld
  433.     mov    di,bx
  434.     mov    ax,ds
  435.     mov    es,ax
  436.     repnz    movs    byte [di],[si]
  437.     mov    PY,di        ;final destination is arg end
  438.     ret
  439. LWX:    mov    di,(offset P0)        ;p0 is destination origin
  440.     cld
  441.     mov    ax,ds
  442.     mov    es,ax
  443.     repnz    movs    byte [di],[si]
  444.     jmp    UCL        ;erase the argument
  445. LWW:    mov    bx,PX        ;create p0...p4 from org,siz
  446.     call    TWOL        ;trnsfr two args from PDL to 8080 stack
  447.     call    LWH        ;place existing header on PDL
  448.     pop    bx        ;recover under arg, namely org
  449.     pop    cx        ;recover upper arg, namely siz
  450.     mov    P0,bx        ;origin of workspace
  451.     mov    P1,bx        ;segment at front of workspace
  452.     add    bx,cx        ;add size
  453.     mov    P2,bx        ;segment traverses whole workspace
  454.     mov    P3,bx        ;which defines end of occupied text
  455.     mov    P4,bx        ;as well as physical end
  456.     ret
  457.  
  458. ;    (U)  Search for interval, excluding limits.  The object
  459. ;    of the search is defined by its delimiters: thus if the
  460. ;    text YYY is to be found, it must be specified as the
  461. ;    one sandwiched between XXX and ZZZ.  Then by executing
  462. ;    'XXX'F followed by 'ZZZ'U pointers 1 and 2 will bracket
  463. ;    YYY.  U erases its argument, whether TRUE or FALSE, by
  464. ;    a custom common to all search or comparison predicates.
  465. ;    By the same custom, pointers 1 and 2 remain unmoved if
  466. ;    the search fails. ''U generates a null interval at the
  467. ;    end of the last interval that was created.
  468.  
  469. UCU:    push    P1        ;fetch beginning of last interval
  470.     mov    ax,P2        ;fetch end of last interval
  471.     mov    P1,ax        ;search begins at end of p1-p2 interval
  472.     push    ax
  473.     call    UCF        ;use the search subroutine
  474.     jmp    UUF        ;search failed [MUST be 3-byte jmp] <===
  475.     mov    ax,P1        ;beginning of found interval
  476.     mov    P2,ax        ;is end of result interval
  477.     pop    P1        ;recover end of last interval
  478.     pop    ax        ;discard beginning of last interval
  479.     jmp    SKP        ;TRUE return from predicate
  480. UUF:    pop    ax        ;discard end of last interval-it's same
  481.     pop    P1        ;recover beginning of last interval
  482.     ret            ;FALSE return from predicate
  483.  
  484. ;    (V)  Search for interval, including limits.  This
  485. ;    predicate is similar to U, the difference being that
  486. ;    after a successful search, p1 and p2 bracket both the
  487. ;    delimiters as well as the text which they define,
  488. ;    whereas U merely brackets the intervening text.
  489.  
  490. UCV:    push    P1        ;pointer to beginning of last interval
  491.     mov    ax,P2
  492.     mov    P1,ax        ;pointer to end of last interval
  493.     call    UCF        ;predicate F always makes the search
  494.     jmp    UVF        ;search failed, F was FALSE
  495.     pop    P1        ;recover the old p1
  496.     jmp    SKP        ;TRUE return with old p1, new p2
  497. UVF:    pop    P1        ;recover original p1
  498.     ret            ;FALSE return with p1 and p2 unchanged
  499.  
  500. ;    (Y)  Recover pointer 1.  There are those times when it
  501. ;    is desirable to note a spot in the workspace, through
  502. ;    qL for example, and then be able to return to it later
  503. ;    on.  However intervening deletions, insertions or even
  504. ;    workspace openings and closings may have rendered it
  505. ;    invalid so a check is made to ensure the preservation
  506. ;    of the relative order of p0, p1, and p3.  If p2 lies
  507. ;    in an acceptable range, it is untouched; otherwise it
  508. ;    is set to define a null interval at p1.
  509.  
  510. UCY:    mov    bx,PX
  511.     mov    cx,PY
  512.     sub    cx,bx
  513.     cmp    cx,4
  514.     jz    UYI
  515.     mov    bx,[bx]        ;fetch low byte of pointer
  516.     cmp    bx,P0        ;check that p1 will be greater or equal
  517.     jnb    UYM        ;if less, store p0 instead
  518.     mov    bx,P0
  519.     jmp    UYZ
  520. UYM:    cmp    P3,bx        ;check that p1 will be less or equal
  521.     jnb    UYN        ;if not, make p2 = p1 = p3
  522.     mov    bx,P3
  523.     jmp    UYY
  524. UYN:    cmp    P2,bx        ;check that p1 less or equal to p2
  525.     jnb    UYZ
  526. UYY:    mov    P2,bx        ;record null interval between p1 and p2
  527. UYZ:    mov    P1,bx        ;give p1 whatever value it'll have
  528.     jmp    CUCL        ;pop the argument
  529. UYI:    mov    cx,[bx]
  530.     mov    bx,2[bx]
  531.     cmp    cx,P0
  532.     jb    UYF
  533.     add    bx,cx
  534.     cmp    P3,bx
  535.     jb    UYF
  536.     mov    P1,cx
  537.     mov    P2,bx
  538.     jmp    CUCL
  539. UYF:    jmp    UCL
  540.  
  541. ;    (z)  Null interval at end of segment.  Equivalent to
  542. ;    ''I, ''U, or 0b.
  543.  
  544. LCZ:    mov    ax,P2        ;pointer to end of interval
  545.     mov    P1,ax        ;make beginning of interval the same
  546.     ret
  547.  
  548. ;    (Z)  Move p2 to the end of the workspace, thereby
  549. ;    extending whatever interval on to the end of the text.
  550.  
  551. UCZ:    mov    ax,P3        ;pointer to the end of text
  552.     mov    P2,ax        ;make end of interval the same
  553.     ret
  554.  
  555. ;    (<)  Close down workspace. The workspace is confined to
  556. ;    the interval between pointers 1 and 2.  The reason for
  557. ;    this could be to restrict the editing operations to a
  558. ;    smaller range, or it could be to have absolute freedom
  559. ;    to work over some material before incorporating it into
  560. ;    the main text.  As a practical matter, the text between
  561. ;    pointers 2 and 3 is displaced to the far end of the
  562. ;    workspace and the original values of pointers 0 and 4
  563. ;    are recorded before setting up the new values of the
  564. ;    pointers. Subsequent insertions and deletions then have
  565. ;    much less material to move.
  566.  
  567. BRA:    mov    di,P4
  568.     mov    si,P3
  569.     mov    cx,di
  570.     sub    cx,si
  571.     sub    cx,4
  572.     jb    BRE
  573.     mov    cx,si
  574.     sub    cx,P2
  575.     dec    di
  576.     dec    si
  577.     std
  578.     mov    ax,ds
  579.     mov    es,ax
  580.     repnz    movs    byte [di],[si]
  581.     dec    di
  582.     mov    ax,P4
  583.     stos    word [di]
  584.     mov    P4,di
  585.     mov    ax,P0
  586.     stos    word [di]
  587.     mov    ax,P2
  588.     mov    P3,ax
  589.     mov    ax,P1
  590.     mov    P0,ax        ;store it as new beginning of text
  591.     ret            ;p2 remains at end of newly made text
  592. BRE:    call    RER
  593.  
  594. ;    (>)  Open up the workspace.  This is the complementary
  595. ;    operator to <, which is used to return the scope of the
  596. ;    pointers p0 and p4 to their original range.  The text
  597. ;    forming the restricted workspace is incorporated in its
  598. ;    entirity in place of the material originally lying in
  599. ;    the interval p1-p2.  An error condition can arise from
  600. ;    opening a workspace that was never closed, but it will
  601. ;    be anulled if a zero address was placed at the pointer
  602. ;    4 during initialization of the workspace.
  603.  
  604. KET:    mov    bx,P4        ;load the end of the universe
  605.     mov    cx,[bx]
  606.     jcxz    KEE        ;zero means opening too many times
  607.     mov    P0,cx        ;restore it
  608.     mov    cx,2[bx]
  609.     mov    P4,cx
  610.     add    bx,4
  611.     sub    cx,bx
  612.     mov    si,bx
  613.     mov    di,P3        ;end of txt is dest to replace old tail
  614.     cld
  615.     mov    ax,ds
  616.     mov    es,ax
  617.     repnz    movs    byte [di],[si]
  618.     mov    P3,di        ;destination end is new end of text
  619.     ret
  620. KEE:    call    RER        ;note error and abandon attempt
  621.  
  622.     END
  623.  
  624.