home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MISC / REC.ZIP / FXT87.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-02-06  |  32.5 KB  |  1,425 lines

  1. ;    =======================================================
  2. ;
  3. ;    REC module containing RAM storage, I/O programs, main
  4. ;    program, and the directory. The complete set of modules
  5. ;    comprises REC.MAC, PDL.MAC, MARKOV.MAC, RECLIB.MAC, and
  6. ;    FXT.MAC.  RECLIB.MAC may be omitted if the operator X
  7. ;    isn't used, and must be substituted by another module
  8. ;    if the collection of subroutines to be called by X is
  9. ;    to be changed.
  10. ;
  11. ;    FXT.MAC contains the following REC operators and
  12. ;    predicates:
  13. ;
  14. ;        C    compile a REC expression
  15. ;        i    input from designated port
  16. ;        k    call CP/M without residue
  17. ;        K    call CP/M, preserve FCB, return value
  18. ;        o    output from designated port
  19. ;        R    read one character from console
  20. ;        t    type message given header
  21. ;        T    type argument on PDL
  22. ;        W    write argument on LST:
  23. ;        `    test if a character waits at keyboard
  24. ;
  25. ;    ------------------------------------------------------
  26. ;    REC version released during the 1984  Summer School of
  27. ;    the Microcomputer Applications Group of the I.C.U.A.P.
  28. ;    ------------------------------------------------------
  29. ;    8086 version with segments for code, PDL and WS.
  30. ;    ------------------------------------------------------
  31. ;
  32. ;         FXT86  -  Copyright (C) 1982, 1984
  33. ;            Universidad Autonoma de Puebla
  34. ;        49 Poniente 1102 -  Puebla, Puebla, Mexico
  35. ;            All Rights Reserved
  36. ;
  37. ;        [Harold V. McIntosh,  28 August 1980]
  38. ;        [Gerardo Cisneros, 8 February 1984]
  39. ;
  40. ;    Modification 1 - 1 January 1981.
  41. ;        a) Main program derives the values of const,
  42. ;          conin, conou from the address rst0 supposing
  43. ;          that BIOS starts out with the standard jump
  44. ;          vector.  Thus, REC need not be reassembled
  45. ;          to have fast access to I/O when CP/M varies.
  46. ;        b) T protected by pushes and pops of dx and bx.
  47. ;        c) Some changes made in memory allocation.
  48. ;    24 May 1981 - Zero flag to restrain L from too many pops
  49. ;    25 March 1982 - Y is now a predicate
  50. ;    29 May 1983 - ~ discontinued as argument exchange
  51. ;    29 May 1983 - ~ for unary negative or complement
  52. ;    29 May 1983 - N for numerical comparison on PDL
  53. ;    29 May 1983 - h discontinued, replaced by ''w
  54. ;    30 May 1983 - CPIR: jumps to BOOT rather than RER
  55. ;    8 July 1983 - C has object program origin as argument
  56. ;    8 July 1983 - C is an operator
  57. ;    8 July 1983 - C0 defined as lower bound of compile area
  58. ;    8 July 1983 - x moved from RECLIB
  59. ;    8 July 1983 - x is a predicate to call REC subroutines
  60. ;    9 July 1983 - Buffered CP/M input if no disk file given
  61. ;    14 July 1983 - W had its arguments reversed
  62. ;    14 January 1984 - <QIN ds 0>, <QOU ds 0> for sorcim.cnv
  63. ;    14 January 1984 - default extension .REC for 1st file
  64. ;    8 February 1984 - separate segments (GCS)
  65. ;    April 1984 - Disposable initialization code - GCS
  66. ;    9 May 1984 - Arguments of C reversed (GCS)
  67. ;    31 May 1984 - Cp, PD and WS ovfl cause termination - GCS
  68. ;    11 June 1984 - DIIN/CPIN set up DMA address and seg. - GCS
  69. ;    18 June 1984 - Set DMA, then open; initialize VT - GCS
  70. ;    20 June 1984 - Rd ovf error on EOF and end of buffer - GCS
  71. ;    3 July 1984 - @@ takes over x, x is library predicate;
  72. ;    entry point for TL and combination table included - GCS
  73. ;    15 Aug 1984 - Operator pair table extended - GCS
  74. ;    29 Jun 1985 - word-sized entries in var/sub tbl; x in. GCS
  75. ;    6 Jul 1985 - Version for MS-DOS. - GCS
  76. ;    29 Jul 1985 - 0<adr>C leaves <adr>,C2-<adr> on PDL- GCS
  77. ;    8 Aug 1985 - Qm added to pair table - GCS
  78. ;    2 Feb 1986 - overflow handling, i fixed - GCS
  79. ;    =======================================================
  80.  
  81. ;    Absolute program locations used by CP/M.
  82.  
  83.  
  84. bdos    equ    021H        ;MS-DOS software interrupt vector
  85.  
  86. DSIZ    equ    0020H        ;size of two parsed filenames
  87. FSIZ    equ    0010H        ;CP/M file name size
  88. TSIZ    equ    0080H        ;CP/M disk buffer size
  89.  
  90.  
  91. ;    Linkage to input-output through ports.
  92.  
  93. QIN:                ;space holder
  94.     DB    0E4H        ;8-bit 8086 static IN instruction
  95. QI    db    00H
  96.     ret
  97.  
  98. QOU:                ;space holder
  99.     DB    0E6H        ;8-bit 8086 static OUT instruction
  100. QO    db    00H
  101.     ret
  102.  
  103. ;    =======================================================
  104. ;    Programs related to input-output and disk usage.
  105. ;    =======================================================
  106.  
  107. ;    bootstrap routine
  108.  
  109. boot:    mov    ax,04C00H
  110.     int    bdos
  111.  
  112.  
  113. ;    Buffer read routine.
  114.  
  115. PTY:    push    bx        ;conserve (bx)
  116.     mov    es,RSEG        ;get segment address for buffer
  117.     mov    bx,RX        ;pointer to read buffer
  118.     cmp    bx,RY
  119.     jz    ptye
  120.     mov    al,es:[bx]        ;fetch byte
  121.     inc    bx        ;advance pointer to next byte
  122.     mov    RX,bx        ;update buffer pointer
  123.     pop    bx        ;restore (bx) - preserve all reg pairs
  124.     ret
  125. ptye:    mov    bx,'dR'        ;report Rd ovfl and quit
  126.     jmp    FERR
  127.  
  128. ;    Console character read routine.  CP/M-86 compatible version
  129. ;    with direct access to CONIN.
  130.  
  131. chin:    push    cx
  132.     push    dx
  133. chi:    mov    dl,-1
  134.     mov    ah,6
  135.     int    bdos
  136.     test    al,al
  137.     jz    chi
  138.     pop    dx
  139.     pop    cx
  140.     ret
  141.  
  142. ;    Buffered console character read routine, which is more
  143. ;    practical for use with CP/M.  Up to 126 characters may
  144. ;    be read using CP/M function 10, which is sufficient for
  145. ;    bootstrapping or generating test programs.  CHIN should
  146. ;    be used for longer input sequences, which must be error
  147. ;    free - incoming through a modem, for example.
  148.  
  149. buin:    push    bx
  150.     push    cx
  151.     push    dx
  152.     mov    bx,RX
  153.     cmp    bx,RY
  154.     jnz    BI5
  155. BI4:    mov    ah,9        ;(09) write message
  156.     mov    dx,(offset bume)
  157.     int    bdos
  158.     mov    ah,10        ;(0A) buffered read
  159.     mov    dx,(offset TBUF)
  160.     int    bdos
  161.     mov    ah,9        ;(09) write message
  162.     mov    dx,(offset crlf)
  163.     int    bdos
  164.     mov    bx,(offset TBUF)+2
  165.     mov    RX,bx
  166.     mov    al,-1[bx]
  167.     mov    ah,0
  168.     add    ax,bx
  169.     cmp    ax,bx
  170.     jz    BI4
  171.     mov    RY,ax
  172. BI5:    mov    al,[bx]
  173.     inc    bx
  174.     mov    RX,bx
  175.     pop    dx
  176.     pop    cx
  177.     pop    bx
  178.     ret
  179.  
  180. ;    Buffered read for repetitive compilation
  181.  
  182. bure:    mov    al,TSIZ-2
  183.     mov    TBUF,al
  184.     mov    ax,(offset buin)
  185.     mov    read,ax
  186.     mov    ax,(offset TBUF)
  187.     mov    RX,ax
  188.     mov    RY,ax
  189.     ret
  190.  
  191. ;    Console character out routine.  CP/M-86 compatible version
  192. ;    with direct access to CONOUT
  193.  
  194. chou:    push    cx
  195.     push    dx
  196.     mov    dl,al
  197.     mov    ah,6        ;(06) direct console IO
  198.     int    bdos
  199.     pop    cx
  200.     pop    dx
  201.     ret
  202.  
  203. ;    (`) Test for presence of waiting character (FALSE if
  204. ;    none waiting.  CP/M-86 compatible version with access
  205. ;    to CONST.
  206.  
  207. chaw:    push    cx
  208.     push    dx
  209. ;    mov    dl,-2
  210.     mov    ah,11        ;(11) Check keyboard status
  211.     int    bdos
  212.     pop    dx
  213.     pop    cx
  214.     test    al,al
  215.     jnz    chw
  216.     ret
  217. chw:    jmp    SKP
  218.  
  219. ;    Printer output routine.
  220.  
  221. PROU:    push    bx
  222.     push    dx
  223.     push    cx
  224.     mov    ah,5        ;(05) output through LST:
  225.     mov    dl,al
  226.     int    bdos
  227.     pop    cx
  228.     pop    dx
  229.     pop    bx
  230.     ret
  231.  
  232. ;    (R) REC read operator.
  233.  
  234. UCR:    mov    cx,1        ;one byte to be inserted
  235.     call    NARG        ;close last arg, verify space
  236.     push    bx
  237.     call    word ptr tyin    ;get byte from console input
  238.     pop    bx
  239.     mov    [bx],al        ;store on PDL
  240.     inc    bx        ;advance pointer
  241.     mov    PY,bx        ;record end of argument
  242.     ret
  243.  
  244. ;    (t) Write indirect operator.  <org,siz,t> prints the
  245. ;    indicated message, leaves no residue.
  246.  
  247. LCT:    mov    bx,PX        ;fetch argument pointer
  248.     call    ONEL        ;move one argument to 8086 stack
  249.     call    CXLD        ;get org and segment
  250.     mov    bx,cx        ;org to bx
  251.     pop    dx        ;size to dx
  252.     add    dx,bx        ;org+size=end
  253.     jmp    UT1        ;use write cycle in UCT
  254.  
  255. ;    (TL)  Often-used combination for which a single call
  256. ;    is compiled.
  257.  
  258. UCTL:    call    UCT        ;type argument and
  259.     jmp    UCL        ;lift it
  260.  
  261. ;    (T) REC write operator. <'XXX' T> will write XXX on
  262. ;    the console, leaving it on the PDL.
  263.  
  264. uct:    mov    dx,PY        ;fetch terminal address
  265.     mov    bx,PX        ;beginning address to (bx)
  266.     mov    ax,ds
  267.     mov    es,ax
  268. ut1:    cmp    dx,bx
  269.     jz    ut2        ;they match, we're done
  270.     mov    al,es:[bx]    ;get byte out of memory
  271.     push    bx
  272.     push    dx
  273.     push    es
  274.     call    word ptr tyou    ;tyou is in the data segment
  275.     pop    es
  276.     pop    dx        ;recover the saved registers
  277.     pop    bx
  278.     inc    bx        ;advance pointer
  279.     jmp    UT1        ;repeat
  280. ut2:    ret
  281.  
  282. ;    (W)  REC print operator.  <org, siz, W> will print the
  283. ;    indicated text on the list device, and then erase its
  284. ;    arguments.
  285.  
  286. UCW:    mov    bx,PX        ;pointer to arguments
  287.     call    ONEL        ;size from PDL to 8086 stack
  288.     call    CXLD        ;org and segment addr to cx and es
  289.     mov    bx,cx        ;place text origin in (bx)
  290.     pop    dx        ;place length in (dx)
  291. UWW:    test    dx,dx        ;check for zero length
  292.     jz    UWX        ;no more to print
  293.     mov    al,es:[bx]    ;fetch a byte
  294.     push    bx        ;we need to be sure that dx and bx are
  295.     push    dx        ;preserved whatever the print routine
  296.     push    es
  297.     call    PROU        ;send it to printer
  298.     pop    es
  299.     pop    dx        ;recover bx
  300.     pop    bx        ;and dx
  301.     dec    dx        ;diminish count
  302.     inc    bx        ;advance pointer
  303.     jmp    UWW        ;repeat
  304. UWX:    ret
  305.  
  306. ;    (i)  Input from designated port.  <port, i> leaves
  307. ;    <port, byte> so that after disposing of <byte>, <port>
  308. ;    can be reused.
  309.  
  310. LCI:    mov    bx,PX        ;get pointer to top argument on PDL
  311.     mov    al,[bx]        ;only the low order byte matters
  312.     mov    cs:QI,al        ;place it in teme IN instruction
  313.     mov    cx,1        ;we're only going to read one byte
  314.     call    NARG        ;prepare a place for it on the PDL
  315.     call    QIN        ;execute the captive IN instruction
  316.     mov    [bx],al        ;storing the incoming byte on the PDL
  317.     inc    bx        ;always ready for the next byte
  318.     mov    PY,bx        ;close off the argument
  319.     ret            ;and we're through
  320.  
  321. ;    (o) Output from designated port  -  <port, byte, o>
  322. ;    leaves <port>, facilitating multiple OUTs through the
  323. ;    same port.
  324.  
  325. LCO:    mov    bx,PX        ;pointer to last argument - output byte
  326.     mov    CH,[bx]        ;tuck it into register b
  327.     call    UCL        ;erase the top argument
  328.     mov    al,[bx]        ;(bx) points to next argument - get it
  329.     mov    cs:QO,al        ;store in tame OUT instruction
  330.     mov    al,CH        ;output must be from accumulator
  331.     jmp    QOU        ;execute the prepared OUT instruction
  332.  
  333. ;    =======================================================
  334. ;
  335. ;    Communication with CP/M takes two forms:  <FCB, n, K>
  336. ;    which leaves <FCB, code> on the pushdown list, or else
  337. ;    <FCB, n, k> which leaves nothing on the pushdown list.
  338. ;    In either case - FCB is a two-byte parameter, usually
  339. ;    the address of the file control block - but it could
  340. ;    also be a DMA address or sometimes even null for the
  341. ;    sake of uniformity.  Approximately thirty options are
  342. ;    available which are numbered serially, indicated by the
  343. ;    argument n.  The difference between K and k is that the
  344. ;    former conserves the parameter FCB for possible use by
  345. ;    a subsequent CP/M call, and reports a result in the
  346. ;    one-byte result <code>.  This could be the character
  347. ;    read by an input routine or an error code for the disk
  348. ;    routines.
  349. ;
  350. ;    The options are:
  351. ;
  352. ;    num    function        "FCB"    "code"
  353. ;    ---    --------        -----    ------
  354. ;
  355. ;    0    system reset        -    -
  356. ;    1    read console        -    char
  357. ;    2    write console        char    -
  358. ;    3    read reader        -    char
  359. ;    4    write punch        char    -
  360. ;    5    write list        char    -
  361. ;    6    -            -    -
  362. ;    7    read i/o stat        -    stat
  363. ;    8    write i/ stat        stat    -
  364. ;    9    print buffer        buffer    -
  365. ;    10    read buffer        buffer    -
  366. ;    11    console status        -    stat
  367. ;
  368. ;    12    lift disk head        -    -
  369. ;    13    init disk only        -    -
  370. ;    14    select disk        disk    -
  371. ;    15    open file        fcb    code
  372. ;    16    close file        fcb    code
  373. ;    17    search once        fcb    code
  374. ;    18    search again        fcb    code
  375. ;    19    delete file        fcb    code
  376. ;    20    read 1 record        fcb    code
  377. ;    21    write 1 record        fcb    code
  378. ;    22    create file        fcb    code
  379. ;    23    rename file        fcb    code
  380. ;    24    read login        -    logv
  381. ;    25    read disklog        -    disk
  382. ;    26    set DMA address     dma    -
  383. ;    27    read bitmap        -    -
  384. ;
  385. ;    Fuller details of all the CP/M options and the way they
  386. ;    function can be obtained through consulting Digital
  387. ;    Research's manuals for CP/M, especially their "CP/M
  388. ;    Interface Guide."
  389. ;
  390. ;    =======================================================
  391.  
  392. ;    (K)  Set up communication with CP/M - top into (bx),
  393. ;    next into (dx).  Preserve next, call BDOS, (Aze) into
  394. ;    top.
  395.  
  396. CPM:    call    DXLD        ;fetch function number and lift
  397.     mov    cx,dx        ;move it to cx
  398.     call    ESLD        ;get FCB org and segment
  399.     mov    dx,[bx]        ;FCB offset to dx
  400. ;    cmp    cx,26        ;is it 'set DMA addr'?
  401. ;    jnz    CPM1
  402. ;    call    CPSG        ;yes, set DMA base first
  403. CPM1:    push    ds        ;save current data seg base
  404.     mov    ah,cl
  405.     mov    cx,es
  406.     mov    ds,cx        ;set ds to FCB's segment
  407.     int    bdos        ;call bdos with args in cx, dx
  408.     pop    ds        ;restore data segment base
  409.     mov    ah,0        ;clear upper half of ax
  410.     push    ax        ;save it on 8086 stack
  411.     call    PUTW        ;transfer to PDL
  412.     ret
  413.  
  414. ;    (k)  Call to CP/M without any value returned.
  415.  
  416. CPML:    mov    bx,PX        ;fetch argument pointer
  417.     call    ONEL        ;function number to 8086 stack
  418.     call    CXLD        ;FCB org and segment to cx and es
  419.     mov    dx,cx        ;we want org in dx
  420.     pop    cx        ;get function number into cx
  421. ;    cmp    cx,26        ;is it 'set DMA base'?
  422. ;    jnz    CPML1        ;no, skip
  423. ;CPML0:    call    CPSG        ;yes, set DMA base
  424. CPML1:    push    ds        ;save data segment base
  425.     mov    ah,cl
  426.     mov    cx,es
  427.     mov    ds,cx        ;set FCB segment base
  428.     int    bdos        ;execute indicated operation
  429.     pop    ds        ;restore data segment base
  430.     ret
  431.  
  432. ;CPSG:    push    es
  433. ;    push    cx
  434. ;    push    dx
  435. ;    mov    ah,51        ;(33H) set DMA base
  436. ;    mov    dx,es        ;the segment base itself
  437. ;    int    bdos
  438. ;    pop    dx
  439. ;    pop    cx
  440. ;    pop    es
  441. ;    ret
  442.  
  443.  
  444. ;    -------------------------------------------------------
  445. ;    Disk input-output routine working through CP/M.
  446. ;    -------------------------------------------------------
  447.  
  448. ;    Set up a file control block with a given file name and
  449. ;    the default extension REC.  The pushdown list contains
  450. ;    the disk unit designation, then by the filename without
  451. ;    any extension. No protection is afforded against an
  452. ;    overly long file name, a nonexistent disk, or the like.
  453. ;    Some errors of this type must be caught by CP/M since
  454. ;    REC cannot know such things as the exact number of disk
  455. ;    drives that there will be.
  456.  
  457. DIIN:    cld
  458.     mov    ax,ds
  459.     mov    es,ax
  460.     mov    cx,11        ;filename field is 11 bytes long
  461.     mov    di,(offset TFCB)+1    ;field begins at second byte
  462.     mov    al,' '        ;fill it with blanks
  463.     repnz    stosb
  464.     mov    bx,PX        ;fetch pointer to top argument
  465.     mov    al,[bx]        ;load disk unit designator
  466.     sub    al,'@'        ;set CP/M disk numbering convention
  467.     mov    TFCB,al        ;store it in file control block
  468.     call    UCL        ;pop top argument
  469.     mov    si,PX        ;fetch pointer to file name
  470.     mov    cx,PY        ;end of file name
  471.     sub    cx,si        ;place py - px in (cx)
  472.     mov    di,(offset TFCB)+1    ;destination origin
  473.     repnz    movsb
  474. CPIN:    cmp    byte ptr TFCB+9,' '
  475.     jnz    CPIN2
  476.     mov    byte ptr TFCB+9,'R'    ;set default extension 'REC'
  477.     mov    byte ptr TFCB+10,'E'
  478.     mov    byte ptr TFCB+11,'C'
  479. CPIN2:    mov    dx,(offset TBUF)    ;origin of CP/M's sector buffer
  480.     mov    RSEG,ds        ;CP/M's buffer is in the data seg
  481.     mov    RX,dx        ;initial address of pseudotty
  482.     mov    RY,dx        ;provoke disk read
  483.     mov    es,RSEG        ;set DMA address and base
  484.     mov    cx,26
  485.     call    CPML1
  486. ;    call    CPML0
  487.     mov    cx,15H        ;clear tail of FCB before opening
  488.     mov    di,(offset TFCB)+12
  489.     mov    al,00H
  490.     repnz    stosb
  491.     mov    ah,15        ;<open file>
  492.     mov    dx,(offset TFCB)    ;file control block
  493.     int    bdos        ;
  494.     cmp    al,0FFH    ;check for error
  495.     jz    CPIR
  496.     ret
  497. CPIR:    jmp    boot
  498.  
  499. ;    Read from disk buffer, replenish buffer when empty.
  500.  
  501. DIRE:    push    bx        ;save 3 8080 register pairs
  502.     push    dx        ;
  503.     push    cx        ;
  504.     mov    bx,RX        ;pointer to current byte
  505.     cmp    bx,RY        ;skip if equal
  506.     jnz    DI5        ;still have bytes in the buffer
  507.     mov    ah,20        ;<read next record>
  508.     mov    dx,(offset TFCB)    ;file control block
  509.     int    bdos        ;
  510.     test    al,al
  511.     jnz    dier        ;quit if read not OK
  512.     mov    bx,(offset TBUF)+TSIZ    ;end of buffer
  513.     mov    RY,bx        ;store it in ry
  514.     mov    bx,(offset TBUF)    ;beginning of buffer
  515.     mov    RX,bx        ;store it in rx
  516. DI5:    mov    al,[bx]        ;common continuation
  517.     inc    bx        ;byte in acc, advance pointer
  518.     mov    RX,bx        ;store position of next byte
  519.     pop    cx        ;replace 3 register pairs
  520.     pop    dx        ;
  521.     pop    bx        ;
  522.     ret
  523. dier:    mov    bx,'dR'        ;report RD ovfl and quit
  524.     jmp    FERR
  525.  
  526. ;    (C) REC compiling operator which takes the designation
  527. ;    of the compiling source from the PDL. The alternatives
  528. ;    are:
  529. ;
  530. ;    ''<dest>C        input program from console
  531. ;    'file' 'D'<dest> C    take<file.rec> from disk D
  532. ;    p<dest>C        pushdown list
  533. ;    q<dest>C        workspace
  534. ;    <org,siz,dest,C>    memory from address org onward
  535. ;
  536. ;    where <dest> designates the destination area for the
  537. ;    compilation: C1 if null, the address given otherwise.
  538. ;    In general, if the top argument is of length zero, the
  539. ;    console is the source, if it is of length one the named
  540. ;    disk is the source [@=current disk, A, B, ... up to the
  541. ;    system's limit], and if the argument has length 2, the
  542. ;    combination of <org, siz> from the memory applies.  It
  543. ;    is the programmer's responsibility to avoid nonexistent
  544. ;    memory, disk units, and the like.
  545.  
  546. UCC:    push    c1
  547.     mov    cx,PY
  548.     sub    cx,PX
  549.     jnz    UC5
  550.     mov    dx,C1        ;use compile pointer
  551.     jmp    UC6
  552. UC5:    call    ESLD        ;get segment, ignore
  553.     mov    dx,[bx]        ;get address to use
  554. UC6:    mov    C1,dx        ;record as C1
  555.     call    UCL        ;remove <dest> argument
  556.     mov    ax,PY        ;check length of <source> argument
  557.     sub    ax,PX
  558.     jz    UC2        ;zero means console
  559.     cmp    ax,1        ;test for one byte
  560.     jz    UC1        ;one means disk designation
  561.     cmp    ax,2        ;verify that we've got two bytes
  562.     jnz    UC7        ;no provision for other than 1, 2 bytes
  563.     mov    bx,(offset PTY)        ;setup readin from pseudoteletype
  564.     mov    read,bx        ;
  565.     call    CXLD        ;load two numerical arguments
  566.     jcxz    UC8        ;zero means return cpl. area ptrs.
  567.     mov    dx,[bx]        ;bx contains PX for second argument
  568.     call    ESLD        ;load segment address of buffer
  569.     mov    RX,dx        ;origin of REC source code
  570.     add    dx,cx        ;length of source code
  571.     mov    RY,dx        ;end of source code
  572.     mov    RSEG,es        ;segment of source code
  573.     jmp    short UC4    ;compile once rx, ry set up
  574. UC8:    mov    bx,C2        ;compute size
  575.     sub    bx,C1
  576.     push    bx        ;size on stack
  577.     push    cs        ;code segment base to stack
  578.     push    C1        ;origin on stack
  579.     call    PUTW        ;C1 on the PDL
  580.     call    PUTW        ;cs too
  581.     call    CONC        ;make a single argument
  582.     jmp    short UC9    ;then to the PDL
  583. UC1:    call    DIIN        ;setup the CP/M FCB for given file
  584.     mov    bx,(offset DIRE)    ;setup input from disk reader
  585.     jmp    UC3        ;compile once input source set up
  586. UC2:    mov    bx,(offset CHIN)    ;input from the console
  587. UC3:    mov    read,bx        ;
  588. UC4:    call    EMCE
  589.     push    dx
  590.     call    PUTW
  591. UC9:    call    PUTW
  592.     pop    c1
  593.     ret
  594. UC7:    pop    c1
  595.     call    RER
  596.  
  597. ;    (X)  noop in this version
  598.  
  599. LIBO:    ret
  600.  
  601.  
  602. ;    Single-shot compilation from a disk file
  603.  
  604. SSHOT:    call    EMCX        ;compile the program file
  605.     mov    dx,(offset TFCB)
  606.     mov    ah,16        ;close the file
  607.     int    bdos
  608.     mov    cx,DSIZ
  609.     mov    di,(offset TFCB)
  610.     mov    si,P3
  611.     mov    ax,ds
  612.     mov    ds,WSEG
  613.     mov    es,ax
  614.     repnz    movsb        ;retrieve parsed filenames
  615.     mov    bx,es:P1
  616.     mov    cl,[bx]
  617.     inc    cx
  618.     mov    di,(offset TBUF)
  619.     mov    si,bx
  620.     repnz    movsb        ;retrieve command line
  621.     mov    ds,ax        ;restore data segment base value
  622.     inc    bx
  623.     mov    P2,bx
  624.     call    UCD        ;delete character count from workspace
  625.     call    EMCU        ;execute the program file
  626.     jmp    short bootie        ;return to CP/M if false
  627.     nop            ;beware jump span
  628. bootie: jmp    boot
  629.  
  630. ;    Multiple compilations from the console
  631.  
  632. tylo:    call    STATS        ;type out memory usage stats
  633. nodi:    call    bure
  634.     call    INRE
  635.     call    EMCX
  636.     call    EMCU
  637.     jmp    short nodi
  638.     nop
  639.     jmp    nodi
  640.  
  641. ;    Report space overflows and quit
  642.  
  643. FERR:    mov    EMSG,bx
  644.     mov    dx,(offset EMSGS)
  645.     mov    ah,9
  646.     int    bdos
  647.     jmp    boot
  648.  
  649. ;    END OF PERMANENT CODE.  THE INSTRUCTIONS FOLLOWING THIS
  650. ;    WILL BE OVERWRITTEN AS SOON AS THE FIRST REC PROGRAM
  651. ;    IS COMPILED.
  652.  
  653. ENDREC:
  654.  
  655. ;    ================
  656. ;    = main program =
  657. ;    ================
  658.  
  659.  
  660. MAIN:
  661. ;    finit
  662.     db    9BH,0DBH,0E3H
  663.     mov    ax,dgroup
  664.     mov    es,ax
  665.     mov    cx,080H
  666.     mov    si,0
  667.     mov    di,si
  668.     cld
  669.     repnz    movsw        ;transfer PSP to data segment
  670.     mov    ax,es
  671.     mov    ds,ax
  672.     mov    di,(offset VT)    ;set up to initialize vars/subs
  673.     mov    cx,021H        ;the number of variables
  674.     mov    ax,0000
  675.     repnz    stosw        ;set variables to zero
  676.     mov    cx,05FH        ;number of subroutine entries
  677. ;    mov    bx,cs
  678.     mov    ax,(offset boot)    ;CP/M exit routine
  679. ;vtc0:    stosw            ;store boot routine address
  680.     repnz    stosw
  681. ;    xchg    ax,bx
  682. ;    stosw            ;store segment base
  683. ;    xchg    ax,bx
  684. ;    loop    vtc0
  685.     mov    bx,02
  686.     mov    dx,cs
  687.     sub    [bx],dx
  688.     mov    ax,[bx]        ;get total No. of paragraphs-c.s.base
  689.     shr    ax,1        ;half of leftover
  690.     mov    dx,01000H    ;tentative size for compile area
  691.     cmp    ax,dx
  692.     jnb    vtc1
  693.     mov    dx,ax        ;less than 128k, use half
  694. vtc1:    sub    [bx],dx        ;subtract c.s.paragraphs
  695.     mov    ax,cs
  696.     add    ax,dx
  697.     mov    es,ax        ;new data segment base
  698.     mov    di,offset dlst
  699.     mov    si,di
  700.     mov    cx,di
  701.     inc    cx
  702.     std
  703.     repnz    movsb        ;move data to new segment
  704.     mov    ax,es
  705.     mov    ds,ax
  706.     mov    cl,4
  707.     shl    dx,cl
  708.     dec    dx        ;sacrifice one byte to avoid C2=0
  709.     mov    C2,dx
  710.     mov    ax,[bx]        ;get leftover
  711.     shr    ax,1
  712.     mov    dx,01000H
  713.     cmp    ax,dx
  714.     jnb    vtc2
  715.     mov    dx,ax
  716. vtc2:    sub    [bx],dx        ;subtract d.s.paragraphs
  717.     mov    ax,ds
  718.     add    ax,dx
  719.     mov    es,ax
  720.     mov    WSEG,ax
  721.     shl    dx,cl        ;first address beyond data segment
  722.     dec    dx
  723.     dec    dx
  724.     xchg    dx,bx
  725.     mov    word ptr [bx],0FFFFH    ;end-of-PDL marker
  726.     mov    PZ,bx
  727.     xchg    dx,bx
  728.     mov    ax,[bx]        ;leftover once more
  729.     shr    ax,1
  730.     mov    dx,01000H
  731.     cmp    ax,dx
  732.     jnb    vtc3
  733.     mov    dx,ax
  734. vtc3:    sub    [bx],dx
  735.     mov    ax,es
  736.     add    ax,dx
  737.     shl    dx,cl
  738.     dec    dx
  739.     dec    dx
  740.     xchg    dx,bx
  741.     mov    es:word ptr [bx],0    ;mark end of ws
  742.     mov    P4,bx
  743.     xchg    dx,bx
  744.     mov    es,ax
  745.     mov    ax,[bx]        ;leftover is for stack
  746.     mov    dx,01000H
  747.     cmp    ax,dx
  748.     jb    vtc4
  749.     mov    ax,dx
  750. vtc4:    shl    ax,cl
  751.     cli
  752.     mov    sp,ax
  753.     mov    ax,es
  754.     mov    ss,ax
  755.     sti
  756.     mov    dx,offset boot
  757.     push    dx
  758.     cmp    byte ptr 05BH[bx],' '
  759.     jnz    majn
  760.     jmp    tylo        ;to TTY: loop if command tail empty
  761. majn:    call    svcmb
  762.     call    CPIN        ;open disk file for REC program
  763.     mov    bx,(offset DIRE)    ;REC input through disk
  764.     mov    read,bx        ;REC compiler's I-O linkage
  765.     call    INRE        ;initialize REC compiler RAM
  766.     jmp    SSHOT        ;compile once from disk file
  767.  
  768. svcmb:    cld
  769.     mov    bx,(offset TBUF)    ;pointer to command buffer
  770.     mov    di,P1    ;next byte of WS
  771.     mov    cl,[bx]    ;get count
  772.     inc    cl    ;plus one to include count itself
  773.     mov    ch,0
  774.     mov    si,bx
  775.     mov    es,WSEG    ;load ES with WS base
  776. mb0:    lodsb
  777.     cmp    al,'a'    ;fold upper into lowercase
  778.     jb    mb1
  779.     cmp    al,'z'
  780.     ja    mb1
  781.     sub    al,32
  782. mb1:    stosb
  783.     loop    mb0
  784.     mov    P3,di
  785.     mov    bx,P1
  786.     inc    bx
  787.     mov    P1,bx
  788.     mov    P2,bx
  789.     mov    ax,ds
  790.     mov    es,ax
  791.     call    fica
  792.     call    UCD    ;delete first name including its terminator
  793.     mov    di,P3    ;save parsed filenames at p3 and following
  794.     mov    es,WSEG    ;reload ES with WS base
  795.     call    ficb
  796.     call    ficb
  797.     mov    bx,P0
  798.     mov    P1,bx    ;p1 back to start of text
  799.     ret
  800.  
  801. fsep:    call    zsep
  802.     jnz    fsep1
  803.     ret
  804. fsep1:    call    rech    ;read one character
  805.     jmp    fsep
  806.  
  807. ;    Advance to a non blank character in the console
  808. ;    buffer unless there is none, indicated by a 00.
  809.  
  810. zonb:    call    rech    ;read one character
  811.     test    al,al
  812.     jnz    zonb1
  813.     ret
  814. zonb1:    cmp    al,' '
  815.     jz    zonb    ;zero or non-blank
  816.     ret
  817.  
  818. ;    Generate a file control block in the manner of CCP.
  819.  
  820. fica:    mov    di,(offset TFCB)
  821. ficb:    call    zonb    ;zero or non-blank
  822.     push    ax
  823.     jz    ficd
  824.     sbb    al,'@'
  825.     mov    dl,al    ;save possible disk id
  826.     mov    bx,P2
  827.     mov    bp,ds
  828.     mov    ds,WSEG
  829.     mov    al,(byte ptr[bx])
  830.     mov    ds,bp
  831.     cmp    al,':'
  832.     jz    ficc
  833.     xor    al,al
  834.     jmp    ficd
  835. ficc:    call    rech    ;get rid of colon
  836.     pop    ax
  837.     call    rech    ;get first of filename
  838.     push    ax
  839.     mov    al,dl
  840. ficd:    stosb
  841.     mov    cx,08
  842.     pop    ax
  843.     call    ffil
  844.     call    fsep
  845.     mov    cx,03
  846.     cmp    al,'.'
  847.     jnz    ficp
  848.     call    rech    ;read one character
  849.     call    ffil
  850.     call    fsep
  851.     jmp    ficq
  852. ficp:    call    bfil
  853. ficq:    mov    cx,04
  854.     mov    ah,al
  855.     mov    al,0
  856.     jmp    kfil
  857.  
  858. ;    Fill a field
  859.  
  860. ffil0:    call    rech    ;read one character
  861. ffil:    call    zsep
  862.     jz    bfil
  863.     cmp    al,'*'
  864.     jz    qfil
  865.     stosb
  866.     loop    ffil0
  867.     ret
  868.  
  869. ;    Block fill
  870.  
  871. qfil:    mov    ah,al
  872.     mov    al,'?'
  873.     jmp    kfil
  874. bfil:    mov    ah,al
  875.     mov    al,' '
  876. kfil:    repnz    stosb
  877.     mov    al,ah
  878.     ret
  879.  
  880. ;    Fetch a character into a from command line
  881.  
  882. rech:    mov    bx,P1
  883.     dec    bx    ;length is kept one back of p1
  884.     mov    si,P2    ;both pointers before altering DS
  885.     mov    bp,ds
  886.     mov    ds,WSEG
  887.     mov    al,(byte ptr[bx])    ;number of characters not taken out
  888.     test    al,al
  889.     mov    al,0DH    ;carriage return faked on empty buffer
  890.     jz    recx
  891.     dec    byte ptr[bx]
  892.     mov    bx,si
  893.     mov    al,byte ptr[bx]
  894.     inc    bx
  895.     mov    ds,bp
  896.     mov    P2,bx
  897. recx:    mov    ds,bp
  898.     ret
  899.  
  900. ;    Set ZF if AL contains a separator
  901.  
  902. zsep:    test    al,al
  903.     jz    zret
  904.     cmp    al,0DH
  905.     jz    zret
  906.     cmp    al,' '
  907.     jc    cmerr    ;ctrl chars
  908.     jz    zret
  909.     cmp    al,'='
  910.     jz    zret
  911.     cmp    al,'_'
  912.     jz    zret
  913.     cmp    al,'.'
  914.     jz    zret
  915.     cmp    al,':'
  916.     jz    zret
  917.     cmp    al,';'
  918.     jz    zret
  919.     cmp    al,'<'
  920.     jz    zret
  921.     cmp    al,'>'
  922. zret:    ret
  923.  
  924. ;    command line error
  925.  
  926. cmerr:    mov    al,'?'
  927.     call    CHOU    ;type a question mark
  928.     pop    bx    ;pop rets from call zsep,
  929.     pop    bx    ;call fsep/ffil,
  930.     pop    bx    ;call fica/b and
  931.     pop    bx    ;call svcmb
  932.     mov    bx,P0    ;restore workspace pointers
  933.     mov    P1,bx
  934.     mov    P2,bx
  935.     mov    P3,bx
  936.  
  937. STATS:    mov    ah,9        ;(09) write message
  938.     mov    dx,(offset logo)
  939.     int    bdos
  940.     call    QU        ;use REC ops to show RAM usage
  941.     dw    6
  942.     db    'Code  '
  943.     MOV    ax,C2
  944.     MOV    cs:stt0,ax
  945.     call    NU
  946.     db    2
  947. stt0    dw    0
  948.     MOV    cs:stt1,cs
  949.     call    NU
  950.     db    2
  951. stt1    dw    0
  952.     call    RLCT
  953.     call    QU
  954.     dw    7
  955.     db    '   CPL '
  956.     mov    bp,C2
  957.     sub    bp,C0
  958.     call    RCTL
  959.     call    QU
  960.     dw    6
  961.     db    'Data  '
  962.     MOV    ax,PZ
  963.     MOV    cs:stt2,ax
  964.     call    NU
  965.     db    2
  966. stt2    dw    0
  967.     MOV    cs:stt3,ds
  968.     call    NU
  969.     db    2
  970. stt3    dw    0
  971.     call    RLCT
  972.     call    QU
  973.     dw    7
  974.     db    '   PDL '
  975.     mov    bp,PZ
  976.     sub    bp,(offset PD)+2
  977.     call    RCTL
  978.     call    QU
  979.     dw    6
  980.     db    'Extra '
  981.     MOV    ax,P4
  982.     MOV    cs:stt4,ax
  983.     call    NU
  984.     db    2
  985. stt4    dw    0
  986.     MOV    ax,WSEG
  987.     MOV    cs:stt5,ax
  988.     call    NU
  989.     db    2
  990. stt5    dw    0
  991.     call    RLCT
  992.     call    QU
  993.     dw    7
  994.     db    '   WS  '
  995.     mov    bp,P4
  996.     sub    bp,P0
  997.     call    RCTL
  998.     call    QU
  999.     dw    6
  1000.     db    'Stack '
  1001.     MOV    cs:stt6,sp
  1002.     call    NU
  1003.     db    2
  1004. stt6    dw    0
  1005.     MOV    cs:stt7,ss
  1006.     call    NU
  1007.     db    2
  1008. stt7    dw    0
  1009.     call    RLCT
  1010.     call    QU
  1011.     dw    7
  1012.     db    '   STK '
  1013.     mov    bp,sp
  1014.     call    RCTL
  1015.     ret
  1016. TCRL:    call    NU
  1017.     db    2
  1018.     dw    2573
  1019.     call    UCT
  1020.     call    UCL
  1021.     ret
  1022. RLCT:    call    HX
  1023.     call    QU
  1024.     dw    1
  1025.     db    ':'
  1026.     call    CONC
  1027.     call    EXCH
  1028.     call    HX
  1029.     call    CONC
  1030.     call    QU
  1031.     dw    1
  1032.     db    'H'
  1033.     call    CONC
  1034. RLCT2:    call    CONC
  1035.     call    UCT
  1036.     call    UCL
  1037.     ret
  1038. RCTL:    mov    cx,2
  1039.     call    NARG
  1040.     mov    [bx],bp
  1041.     inc    bx
  1042.     inc    bx
  1043.     mov    PY,bx
  1044.     call    NS
  1045.     call    RLCT2
  1046.     call    TCRL
  1047.     ret
  1048.  
  1049. code    ends
  1050.  
  1051. ;    -----------------------------------------------------
  1052. ;    RAM memory which is required for the operation of REC
  1053. ;    -----------------------------------------------------
  1054.  
  1055. ;    =============
  1056. pdlist    segment
  1057.         org    0
  1058. dsbeg    db    05CH dup(?)
  1059. TFCB    db    024H dup(?)
  1060. TBUF    db    ?
  1061.     org    0100H        ;origin of data in data segment
  1062. ;    =============
  1063.  
  1064. ;    Relay area for input and output subroutines.
  1065.  
  1066. read    dw    chin        ;character input for REC compiler
  1067. tyin    dw    chin        ;single character input for R
  1068. tyou    dw    chou        ;single character output for T
  1069.  
  1070. ;    Error message buffer
  1071.  
  1072. EMSGS    db    0DH,0AH
  1073. EMSG    dw    2020H
  1074.     db    ' ovfl$'
  1075.  
  1076. ;    Prompt and crlf
  1077.  
  1078. bume    db    0DH,0AH,'REC87> $'
  1079. crlf    db    0DH,0AH,'$'
  1080.  
  1081. ;    Temporary storage used by the REC compiler.
  1082.  
  1083. XPD    dw    0000        ;colon jump back to left parenthesis
  1084. YPD    dw    0000        ;false predicate jump chain
  1085. ZPD    dw    0000        ;semicolon exit chain
  1086.  
  1087. ;    Pointers to the directories.
  1088.  
  1089. FXT    dw    FT        ;pointer to fixed operator directory
  1090. VRT    dw    VT        ;pointer to variable directory
  1091. SBT    dw    STB        ;pointer to subroutine directory
  1092. CMT    dw    CTB        ;pointer to compination directory
  1093.  
  1094.  
  1095. ;    Pointers to the area of compiled subroutines.
  1096.  
  1097. C0    dw    ENDREC        ;lower limit of compile area
  1098. C1    dw    ENDREC        ;beginning of present compilation
  1099. C2    dw    0        ;upper limit of compile area
  1100.  
  1101. ;    Pointers to REC/MARKOV pushdown list.
  1102.  
  1103. PX    dw    PD+2        ;beginning of pushdown text
  1104. PY    dw    PD+2        ;end of pushdown text
  1105. PZ    dw    0        ;end of available pushdown space
  1106.  
  1107. ;    Workspace pointers.
  1108.  
  1109. P0    dw    0        ;beginning of workspace
  1110. P1    dw    0        ;beginning of marked segment
  1111. P2    dw    0        ;end of marked segment
  1112. P3    dw    0        ;end of text
  1113. P4    dw    0        ;end of workspace
  1114. WSEG    dw    0        ;WS segment address
  1115.  
  1116. ;    Number conversion and arithmetic buffers
  1117.  
  1118. FRST    db    0    ;first character of input string
  1119. ARG1    dw    0,0    ;8-byte buffer for digit collection
  1120. ARG1M    db    0
  1121. ARG1X    db    0
  1122. ARG1B    db    0
  1123. ARG1H    db    0
  1124. ARGHH    db    0
  1125. DCPT    db    0    ;decimal point flag and
  1126. DDCT    db    0    ;decimal digit count
  1127. BINXPT    equ    DCPT
  1128. ARG2    dw    0    ;alternate 8-byte buffer
  1129. ARG2B    dw    0
  1130. ARG2M    db    0,0,0
  1131. ARG2H    db    0
  1132. DCXPT    dw    0    ;decimal exponent
  1133. DXSG    db    0    ;flag for sign of decimal exponent
  1134. NSIZ    db    0    ;operand size in bytes
  1135.  
  1136. ;    I-O pointers.
  1137.  
  1138. RX    dw    0000
  1139. RY    dw    0000
  1140. RSEG    dw    0000
  1141.  
  1142. ;    Error flag.
  1143.  
  1144. ER    dw    0000
  1145.  
  1146. ;    Holder for return address from h
  1147.  
  1148. RTADDR    dw    0000
  1149.  
  1150. ;    ======= here is the table of definitions of REC operators =====
  1151.  
  1152. FT    dw    NOOP        ;blank
  1153.     dw    NOOP
  1154.     dw    RECOP        ; [exclm]    binary to hex string
  1155.     dw    HX
  1156.     dw    RECDQ        ; "    quoted expression
  1157.     dw    QU
  1158.     dw    RECOP        ; #    binary to decimal string
  1159.     dw    NS
  1160.     dw    RECOL        ; $    fetch a variable cell
  1161.     dw    VBLE
  1162.     dw    RECOP        ; %    restrict to one byte
  1163.     dw    PE
  1164.     dw    RECOL        ; &    exchange top numeric pair
  1165.     dw    EXCH
  1166.     dw    RECSQ        ; '    quoted expression
  1167.     dw    QU
  1168.     dw    RECLP        ; (
  1169.     dw    NOOP
  1170.     dw    RECRP        ; )
  1171.     dw    NOOP
  1172.     dw    RECOP        ; *    multiply
  1173.     dw    MPY
  1174.     dw    RECOP        ; +    add
  1175.     dw    SUM
  1176.     dw    NOOP        ; ,    separator like space
  1177.     dw    NOOP
  1178.     dw    RECMS        ; -    subtract
  1179.     dw    DIF
  1180.     dw    RECDD        ; .    decimal point
  1181.     dw    NU
  1182.     dw    RECOP        ; /    divide [remainder, quotient]
  1183.     dw    DVD
  1184.     dw    RECDD        ; 0    number
  1185.     dw    NU
  1186.     dw    RECDD        ; 1    number
  1187.     dw    NU
  1188.     dw    RECDD        ; 2    number
  1189.     dw    NU
  1190.     dw    RECDD        ; 3    number
  1191.     dw    NU
  1192.     dw    RECDD        ; 4    number
  1193.     dw    NU
  1194.     dw    RECDD        ; 5    number
  1195.     dw    NU
  1196.     dw    RECDD        ; 6    number
  1197.     dw    NU
  1198.     dw    RECDD        ; 7    number
  1199.     dw    NU
  1200.     dw    RECDD        ; 8    number
  1201.     dw    NU
  1202.     dw    RECDD        ; 9    number
  1203.     dw    NU
  1204.     dw    RECCO        ; :
  1205.     dw    NOOP
  1206.     dw    RECSC        ;    ;
  1207.     dw    NOOP
  1208.     dw    RECOP        ; <    restrict workspace
  1209.     dw    BRA
  1210.     dw    RECPR        ; =    test equality of top pair
  1211.     dw    EQL
  1212.     dw    RECOL        ; >    open workspace
  1213.     dw    KET
  1214.     dw    RECPR        ; ?    test for error report
  1215.     dw    QM
  1216.     dw    RECP1        ; @    execute subroutine
  1217.     dw    AR
  1218.     dw    RECPR        ; A    advance pointer 1
  1219.     dw    UCA
  1220.     dw    RECPR        ; B    retract pointer 1
  1221.     dw    UCB
  1222.     dw    RECOP        ; C    compile
  1223.     dw    UCC
  1224.     dw    RECOP        ; D    delete text
  1225.     dw    UCD
  1226.     dw    RECPL        ; E    equality between WS and PD
  1227.     dw    UCE
  1228.     dw    RECPL        ; F    find specified text
  1229.     dw    UCF
  1230.     dw    RECOP        ; G    fetch a block from memory
  1231.     dw    GA
  1232.     dw    RECPR        ; H    ASCII hex to binary
  1233.     dw    HE
  1234.     dw    RECOL        ; I    insert
  1235.     dw    UCI
  1236.     dw    RECOL        ; J    jump to front
  1237.     dw    UCJ
  1238.     dw    RECOP        ; K    call CP/M, keep (dx), put value
  1239.     dw    CPM
  1240.     dw    RECOL        ; L    erase top of PDL
  1241.     dw    UCL
  1242.     dw    RECPR        ; M    compare PDL and workspace
  1243.     dw    UCM
  1244.     dw    RECPR        ; N    numerical comparison
  1245.     dw    UCN
  1246.     dw    RECPR        ; O    decimal ASCII string to binary
  1247.     dw    UCO
  1248.     dw    RECOP        ; P    put block into buffered memory
  1249.     dw    UCP
  1250.     dw    RECOL        ; Q    put workspace segment on PD
  1251.     dw    UCQ
  1252.     dw    RECOP        ; R    read from keyboard
  1253.     dw    UCR
  1254.     dw    RECOP        ; S    store block in memory
  1255.     dw    SA
  1256.     dw    RECOL        ; T    write on screen
  1257.     dw    UCT
  1258.     dw    RECPR        ; U    search, yielding interval
  1259.     dw    UCU
  1260.     dw    RECPR        ; V    U, including endpoints
  1261.     dw    UCV
  1262.     dw    RECOP        ; W    write on printer
  1263.     dw    UCW
  1264.     dw    RECO1        ; X    call library operator
  1265.     dw    LIBO
  1266.     dw    RECPR        ; Y    recover previous position of p1
  1267.     dw    UCY
  1268.     dw    RECOL        ; Z    pointer 2 to end of text
  1269.     dw    UCZ
  1270.     dw    RECCM        ; [    comment
  1271.     dw    NOOP
  1272.     dw    RECOP        ; \    insert single byte in pair
  1273.     dw    IP
  1274.     dw    RECOP        ; ]
  1275.     dw    NOOP
  1276.     dw    RECOL        ; ^    increment top argument
  1277.     dw    INCR
  1278.     dw    RECOP        ; _    exit to monitor
  1279.     dw    boot
  1280.     dw    RECPR        ; `    true for waiting character
  1281.     dw    CHAW
  1282.     dw    RECPR        ; a    segment forward from p1
  1283.     dw    LCA
  1284.     dw    RECPR        ; b    segment backward from p2
  1285.     dw    LCB
  1286.     dw    RECOP        ; c    create block on PDL
  1287.     dw    BLOK
  1288.     dw    RECPR        ; d    decrement but skip on zero
  1289.     dw    decR
  1290.     dw    RECPR        ; e    extend workspace
  1291.     dw    LCE
  1292.     dw    RECPR        ; f    block fill
  1293.     dw    LCF
  1294.     dw    RECOP        ; g    non-incrementing byte fetch
  1295.     dw    GB
  1296.     dw    RECOP        ; h    store/restore machine state
  1297.     dw    MST
  1298.     dw    RECOP        ; i    input from designated port
  1299.     dw    LCI
  1300.     dw    RECOL        ; j    null interval at p1
  1301.     dw    LCJ
  1302.     dw    RECOP        ; k    call CP/M: no returned values
  1303.     dw    CPML
  1304.     dw    RECOP        ; l    put pz on PDL
  1305.     dw    Lcl
  1306.     dw    RECOP        ; m    set aside top argument
  1307.     dw    LCM
  1308.     dw    RECOL        ; n    recover set-aside argument
  1309.     dw    LCN
  1310.     dw    RECOP        ; o    output from designated port
  1311.     dw    LCO
  1312.     dw    RECOL        ; p    put px, py-px on PDL
  1313.     dw    GXS
  1314.     dw    RECOL        ; q    put p1, p2-p1 on PDL
  1315.     dw    LCQ
  1316.     dw    RECOP        ; r    indirect replacement of address
  1317.     dw    IND
  1318.     dw    RECOP        ; s    store block in memory wrt limit
  1319.     dw    LCS
  1320.     dw    RECOP        ; t    type out indicated interval
  1321.     dw    LCT
  1322.     dw    RECOP        ; u    incrementing byte fetch
  1323.     dw    GBI
  1324.     dw    RECOP        ; v    incrementing byte store
  1325.     dw    SAI
  1326.     dw    RECOP        ; w    store workspace header
  1327.     dw    LCW
  1328.     dw    RECP1        ; x    call library predicate
  1329.     dw    LIBP
  1330.     dw    RECOP        ; y    fetch byte pair to PDL incr org
  1331.     dw    GWI
  1332.     dw    RECOL        ; z    null interval at p2
  1333.     dw    LCZ
  1334.     dw    LBR        ; {    start a definition string
  1335.     dw    NOOP
  1336.     dw    RECOP        ; |    concatinate top two arguments
  1337.     dw    CONC
  1338.     dw    RECOP        ; }    end a definition string
  1339.     dw    NOOP
  1340.     dw    RECOP        ; ~    complement or negate top arg
  1341.     dw    COMP
  1342.     dw    RECOP        ; del
  1343.     dw    NOOP
  1344.  
  1345. ;    Table of often-used combinations to compile as single
  1346. ;    operators or predicates.
  1347.  
  1348. CTB    db    'Ez'        ;to the right if same
  1349.     dw    EZE
  1350.     db    'JZ'        ;span text
  1351.     dw    SPAN
  1352.     db    'z<'        ;null WS at p2
  1353.     dw    ZCL
  1354.     db    'Z>'        ;reopen with p2 at end
  1355.     dw    ZOP
  1356.     db    'Jj'        ;p1 and p2 at p0
  1357.     dw    BEG
  1358.     db    'Z<'        ;restrict from p1 to p3
  1359.     dw    UZCL
  1360.     db    'pG'        ;duplicate PDL argument
  1361.     dw    DUPP
  1362.     db    'ED'        ;delete if same
  1363.     dw    EDE
  1364.     db    'J>'        ;open with p1 at old p0
  1365.     dw    JOP
  1366.     db    'Iz'        ;insert and collapse
  1367.     dw    IZE
  1368.     db    'jJ'        ;p1 and p2 to p0 and p1
  1369.     dw    LJUJ
  1370.     db    '><'        ;reopen and restrict
  1371.     dw    OPCL
  1372.     db    '^^'        ;increase by 2
  1373.     dw    INTW
  1374.     db    'QD'        ;copy and delete
  1375.     dw    QUDE
  1376.     db    'FD'        ;find and delete
  1377.     dw    EFDE
  1378.     db    'nL'        ;lift from PDL complement
  1379.     dw    ENLF
  1380.     db    '&S'        ;exch args and store
  1381.     dw    XSTO
  1382.     db    'LL'        ;lift twice
  1383.     dw    LFTW
  1384.     db    '$r'        ;contents of var cell
  1385.     dw    VREP
  1386.     db    '$S'        ;save in var cell
  1387.     dw    VSTO
  1388.     db    '&L'        ;lift lower
  1389.     dw    XLFT
  1390.     db    'qL'        ;p1 to PDL
  1391.     dw    GTP1
  1392.     db    'J<'        ;restrict from p0
  1393.     dw    JCL
  1394.     db    'I<'        ;insert and restrict
  1395.     dw    ICL
  1396.     db    'TL'        ;type and lift
  1397.     dw    UCTL
  1398.     db    'Qm'        ;copy WS to PDL complement
  1399.     dw    QUEM
  1400.     dw    0000        ;end-of-table marker
  1401.  
  1402. VT    dw    021H dup(?)    ;REC-defined subroutine table & vars.
  1403. STB    dw    05FH dup(?)
  1404. PD    dw    0        ;beginning of PDL
  1405.  
  1406. logo    db    0DH,0AH,'       REC(8086)/ICUAP',0DH,0AH
  1407.     db    'Universidad Autonoma de Puebla',0DH,0AH
  1408.     db    '       February 2, 1986',0DH,0AH,0AH,'$'
  1409.  
  1410. dlst    db    0
  1411.  
  1412. pdlist    ends
  1413.  
  1414. ;    =============
  1415. stack    segment    STACK
  1416.     org    0000H        ;origin of stack segment
  1417. ;    =============
  1418.  
  1419. STKB    dw    0
  1420. STKE    dw    0
  1421. stack    ends
  1422.  
  1423.  
  1424. ;    end
  1425.