home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MISC / REC.ZIP / MKV86.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-07-07  |  22.0 KB  |  714 lines

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