home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MISC / REC.ZIP / FXT86F.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-02-04  |  32.5 KB  |  1,422 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:    mov    ax,dgroup
  661.     mov    es,ax
  662.     mov    cx,080H
  663.     mov    si,0
  664.     mov    di,si
  665.     cld
  666.     repnz    movsw        ;transfer PSP to data segment
  667.     mov    ax,es
  668.     mov    ds,ax
  669.     mov    di,(offset VT)    ;set up to initialize vars/subs
  670.     mov    cx,021H        ;the number of variables
  671.     mov    ax,0000
  672.     repnz    stosw        ;set variables to zero
  673.     mov    cx,05FH        ;number of subroutine entries
  674. ;    mov    bx,cs
  675.     mov    ax,(offset boot)    ;CP/M exit routine
  676. ;vtc0:    stosw            ;store boot routine address
  677.     repnz    stosw
  678. ;    xchg    ax,bx
  679. ;    stosw            ;store segment base
  680. ;    xchg    ax,bx
  681. ;    loop    vtc0
  682.     mov    bx,02
  683.     mov    dx,cs
  684.     sub    [bx],dx
  685.     mov    ax,[bx]        ;get total No. of paragraphs-c.s.base
  686.     shr    ax,1        ;half of leftover
  687.     mov    dx,01000H    ;tentative size for compile area
  688.     cmp    ax,dx
  689.     jnb    vtc1
  690.     mov    dx,ax        ;less than 128k, use half
  691. vtc1:    sub    [bx],dx        ;subtract c.s.paragraphs
  692.     mov    ax,cs
  693.     add    ax,dx
  694.     mov    es,ax        ;new data segment base
  695.     mov    di,offset dlst
  696.     mov    si,di
  697.     mov    cx,di
  698.     inc    cx
  699.     std
  700.     repnz    movsb        ;move data to new segment
  701.     mov    ax,es
  702.     mov    ds,ax
  703.     mov    cl,4
  704.     shl    dx,cl
  705.     dec    dx        ;sacrifice one byte to avoid C2=0
  706.     mov    C2,dx
  707.     mov    ax,[bx]        ;get leftover
  708.     shr    ax,1
  709.     mov    dx,01000H
  710.     cmp    ax,dx
  711.     jnb    vtc2
  712.     mov    dx,ax
  713. vtc2:    sub    [bx],dx        ;subtract d.s.paragraphs
  714.     mov    ax,ds
  715.     add    ax,dx
  716.     mov    es,ax
  717.     mov    WSEG,ax
  718.     shl    dx,cl        ;first address beyond data segment
  719.     dec    dx
  720.     dec    dx
  721.     xchg    dx,bx
  722.     mov    word ptr [bx],0FFFFH    ;end-of-PDL marker
  723.     mov    PZ,bx
  724.     xchg    dx,bx
  725.     mov    ax,[bx]        ;leftover once more
  726.     shr    ax,1
  727.     mov    dx,01000H
  728.     cmp    ax,dx
  729.     jnb    vtc3
  730.     mov    dx,ax
  731. vtc3:    sub    [bx],dx
  732.     mov    ax,es
  733.     add    ax,dx
  734.     shl    dx,cl
  735.     dec    dx
  736.     dec    dx
  737.     xchg    dx,bx
  738.     mov    es:word ptr [bx],0    ;mark end of ws
  739.     mov    P4,bx
  740.     xchg    dx,bx
  741.     mov    es,ax
  742.     mov    ax,[bx]        ;leftover is for stack
  743.     mov    dx,01000H
  744.     cmp    ax,dx
  745.     jb    vtc4
  746.     mov    ax,dx
  747. vtc4:    shl    ax,cl
  748.     cli
  749.     mov    sp,ax
  750.     mov    ax,es
  751.     mov    ss,ax
  752.     sti
  753.     mov    dx,offset boot
  754.     push    dx
  755.     cmp    byte ptr 05BH[bx],' '
  756.     jnz    majn
  757.     jmp    tylo        ;to TTY: loop if command tail empty
  758. majn:    call    svcmb
  759.     call    CPIN        ;open disk file for REC program
  760.     mov    bx,(offset DIRE)    ;REC input through disk
  761.     mov    read,bx        ;REC compiler's I-O linkage
  762.     call    INRE        ;initialize REC compiler RAM
  763.     jmp    SSHOT        ;compile once from disk file
  764.  
  765. svcmb:    cld
  766.     mov    bx,(offset TBUF)    ;pointer to command buffer
  767.     mov    di,P1    ;next byte of WS
  768.     mov    cl,[bx]    ;get count
  769.     inc    cl    ;plus one to include count itself
  770.     mov    ch,0
  771.     mov    si,bx
  772.     mov    es,WSEG    ;load ES with WS base
  773. mb0:    lodsb
  774.     cmp    al,'a'    ;fold upper into lowercase
  775.     jb    mb1
  776.     cmp    al,'z'
  777.     ja    mb1
  778.     sub    al,32
  779. mb1:    stosb
  780.     loop    mb0
  781.     mov    P3,di
  782.     mov    bx,P1
  783.     inc    bx
  784.     mov    P1,bx
  785.     mov    P2,bx
  786.     mov    ax,ds
  787.     mov    es,ax
  788.     call    fica
  789.     call    UCD    ;delete first name including its terminator
  790.     mov    di,P3    ;save parsed filenames at p3 and following
  791.     mov    es,WSEG    ;reload ES with WS base
  792.     call    ficb
  793.     call    ficb
  794.     mov    bx,P0
  795.     mov    P1,bx    ;p1 back to start of text
  796.     ret
  797.  
  798. fsep:    call    zsep
  799.     jnz    fsep1
  800.     ret
  801. fsep1:    call    rech    ;read one character
  802.     jmp    fsep
  803.  
  804. ;    Advance to a non blank character in the console
  805. ;    buffer unless there is none, indicated by a 00.
  806.  
  807. zonb:    call    rech    ;read one character
  808.     test    al,al
  809.     jnz    zonb1
  810.     ret
  811. zonb1:    cmp    al,' '
  812.     jz    zonb    ;zero or non-blank
  813.     ret
  814.  
  815. ;    Generate a file control block in the manner of CCP.
  816.  
  817. fica:    mov    di,(offset TFCB)
  818. ficb:    call    zonb    ;zero or non-blank
  819.     push    ax
  820.     jz    ficd
  821.     sbb    al,'@'
  822.     mov    dl,al    ;save possible disk id
  823.     mov    bx,P2
  824.     mov    bp,ds
  825.     mov    ds,WSEG
  826.     mov    al,(byte ptr[bx])
  827.     mov    ds,bp
  828.     cmp    al,':'
  829.     jz    ficc
  830.     xor    al,al
  831.     jmp    ficd
  832. ficc:    call    rech    ;get rid of colon
  833.     pop    ax
  834.     call    rech    ;get first of filename
  835.     push    ax
  836.     mov    al,dl
  837. ficd:    stosb
  838.     mov    cx,08
  839.     pop    ax
  840.     call    ffil
  841.     call    fsep
  842.     mov    cx,03
  843.     cmp    al,'.'
  844.     jnz    ficp
  845.     call    rech    ;read one character
  846.     call    ffil
  847.     call    fsep
  848.     jmp    ficq
  849. ficp:    call    bfil
  850. ficq:    mov    cx,04
  851.     mov    ah,al
  852.     mov    al,0
  853.     jmp    kfil
  854.  
  855. ;    Fill a field
  856.  
  857. ffil0:    call    rech    ;read one character
  858. ffil:    call    zsep
  859.     jz    bfil
  860.     cmp    al,'*'
  861.     jz    qfil
  862.     stosb
  863.     loop    ffil0
  864.     ret
  865.  
  866. ;    Block fill
  867.  
  868. qfil:    mov    ah,al
  869.     mov    al,'?'
  870.     jmp    kfil
  871. bfil:    mov    ah,al
  872.     mov    al,' '
  873. kfil:    repnz    stosb
  874.     mov    al,ah
  875.     ret
  876.  
  877. ;    Fetch a character into a from command line
  878.  
  879. rech:    mov    bx,P1
  880.     dec    bx    ;length is kept one back of p1
  881.     mov    si,P2    ;both pointers before altering DS
  882.     mov    bp,ds
  883.     mov    ds,WSEG
  884.     mov    al,(byte ptr[bx])    ;number of characters not taken out
  885.     test    al,al
  886.     mov    al,0DH    ;carriage return faked on empty buffer
  887.     jz    recx
  888.     dec    byte ptr[bx]
  889.     mov    bx,si
  890.     mov    al,byte ptr[bx]
  891.     inc    bx
  892.     mov    ds,bp
  893.     mov    P2,bx
  894. recx:    mov    ds,bp
  895.     ret
  896.  
  897. ;    Set ZF if AL contains a separator
  898.  
  899. zsep:    test    al,al
  900.     jz    zret
  901.     cmp    al,0DH
  902.     jz    zret
  903.     cmp    al,' '
  904.     jc    cmerr    ;ctrl chars
  905.     jz    zret
  906.     cmp    al,'='
  907.     jz    zret
  908.     cmp    al,'_'
  909.     jz    zret
  910.     cmp    al,'.'
  911.     jz    zret
  912.     cmp    al,':'
  913.     jz    zret
  914.     cmp    al,';'
  915.     jz    zret
  916.     cmp    al,'<'
  917.     jz    zret
  918.     cmp    al,'>'
  919. zret:    ret
  920.  
  921. ;    command line error
  922.  
  923. cmerr:    mov    al,'?'
  924.     call    CHOU    ;type a question mark
  925.     pop    bx    ;pop rets from call zsep,
  926.     pop    bx    ;call fsep/ffil,
  927.     pop    bx    ;call fica/b and
  928.     pop    bx    ;call svcmb
  929.     mov    bx,P0    ;restore workspace pointers
  930.     mov    P1,bx
  931.     mov    P2,bx
  932.     mov    P3,bx
  933.  
  934. STATS:    mov    ah,9        ;(09) write message
  935.     mov    dx,(offset logo)
  936.     int    bdos
  937.     call    QU        ;use REC ops to show RAM usage
  938.     dw    6
  939.     db    'Code  '
  940.     MOV    ax,C2
  941.     MOV    cs:stt0,ax
  942.     call    NU
  943.     db    2
  944. stt0    dw    0
  945.     MOV    cs:stt1,cs
  946.     call    NU
  947.     db    2
  948. stt1    dw    0
  949.     call    RLCT
  950.     call    QU
  951.     dw    7
  952.     db    '   CPL '
  953.     mov    bp,C2
  954.     sub    bp,C0
  955.     call    RCTL
  956.     call    QU
  957.     dw    6
  958.     db    'Data  '
  959.     MOV    ax,PZ
  960.     MOV    cs:stt2,ax
  961.     call    NU
  962.     db    2
  963. stt2    dw    0
  964.     MOV    cs:stt3,ds
  965.     call    NU
  966.     db    2
  967. stt3    dw    0
  968.     call    RLCT
  969.     call    QU
  970.     dw    7
  971.     db    '   PDL '
  972.     mov    bp,PZ
  973.     sub    bp,(offset PD)+2
  974.     call    RCTL
  975.     call    QU
  976.     dw    6
  977.     db    'Extra '
  978.     MOV    ax,P4
  979.     MOV    cs:stt4,ax
  980.     call    NU
  981.     db    2
  982. stt4    dw    0
  983.     MOV    ax,WSEG
  984.     MOV    cs:stt5,ax
  985.     call    NU
  986.     db    2
  987. stt5    dw    0
  988.     call    RLCT
  989.     call    QU
  990.     dw    7
  991.     db    '   WS  '
  992.     mov    bp,P4
  993.     sub    bp,P0
  994.     call    RCTL
  995.     call    QU
  996.     dw    6
  997.     db    'Stack '
  998.     MOV    cs:stt6,sp
  999.     call    NU
  1000.     db    2
  1001. stt6    dw    0
  1002.     MOV    cs:stt7,ss
  1003.     call    NU
  1004.     db    2
  1005. stt7    dw    0
  1006.     call    RLCT
  1007.     call    QU
  1008.     dw    7
  1009.     db    '   STK '
  1010.     mov    bp,sp
  1011.     call    RCTL
  1012.     ret
  1013. TCRL:    call    NU
  1014.     db    2
  1015.     dw    2573
  1016.     call    UCT
  1017.     call    UCL
  1018.     ret
  1019. RLCT:    call    HX
  1020.     call    QU
  1021.     dw    1
  1022.     db    ':'
  1023.     call    CONC
  1024.     call    EXCH
  1025.     call    HX
  1026.     call    CONC
  1027.     call    QU
  1028.     dw    1
  1029.     db    'H'
  1030.     call    CONC
  1031. RLCT2:    call    CONC
  1032.     call    UCT
  1033.     call    UCL
  1034.     ret
  1035. RCTL:    mov    cx,2
  1036.     call    NARG
  1037.     mov    [bx],bp
  1038.     inc    bx
  1039.     inc    bx
  1040.     mov    PY,bx
  1041.     call    NS
  1042.     call    RLCT2
  1043.     call    TCRL
  1044.     ret
  1045.  
  1046. code    ends
  1047.  
  1048. ;    -----------------------------------------------------
  1049. ;    RAM memory which is required for the operation of REC
  1050. ;    -----------------------------------------------------
  1051.  
  1052. ;    =============
  1053. pdlist    segment
  1054.         org    0
  1055. dsbeg    db    05CH dup(?)
  1056. TFCB    db    024H dup(?)
  1057. TBUF    db    ?
  1058.     org    0100H        ;origin of data in data segment
  1059. ;    =============
  1060.  
  1061. ;    Relay area for input and output subroutines.
  1062.  
  1063. read    dw    chin        ;character input for REC compiler
  1064. tyin    dw    chin        ;single character input for R
  1065. tyou    dw    chou        ;single character output for T
  1066.  
  1067. ;    Error message buffer
  1068.  
  1069. EMSGS    db    0DH,0AH
  1070. EMSG    dw    2020H
  1071.     db    ' ovfl$'
  1072.  
  1073. ;    Prompt and crlf
  1074.  
  1075. bume    db    0DH,0AH,'REC86F> $'
  1076. crlf    db    0DH,0AH,'$'
  1077.  
  1078. ;    Temporary storage used by the REC compiler.
  1079.  
  1080. XPD    dw    0000        ;colon jump back to left parenthesis
  1081. YPD    dw    0000        ;false predicate jump chain
  1082. ZPD    dw    0000        ;semicolon exit chain
  1083.  
  1084. ;    Pointers to the directories.
  1085.  
  1086. FXT    dw    FT        ;pointer to fixed operator directory
  1087. VRT    dw    VT        ;pointer to variable directory
  1088. SBT    dw    STB        ;pointer to subroutine directory
  1089. CMT    dw    CTB        ;pointer to compination directory
  1090.  
  1091.  
  1092. ;    Pointers to the area of compiled subroutines.
  1093.  
  1094. C0    dw    ENDREC        ;lower limit of compile area
  1095. C1    dw    ENDREC        ;beginning of present compilation
  1096. C2    dw    0        ;upper limit of compile area
  1097.  
  1098. ;    Pointers to REC/MARKOV pushdown list.
  1099.  
  1100. PX    dw    PD+2        ;beginning of pushdown text
  1101. PY    dw    PD+2        ;end of pushdown text
  1102. PZ    dw    0        ;end of available pushdown space
  1103.  
  1104. ;    Workspace pointers.
  1105.  
  1106. P0    dw    0        ;beginning of workspace
  1107. P1    dw    0        ;beginning of marked segment
  1108. P2    dw    0        ;end of marked segment
  1109. P3    dw    0        ;end of text
  1110. P4    dw    0        ;end of workspace
  1111. WSEG    dw    0        ;WS segment address
  1112.  
  1113. ;    Number conversion and arithmetic buffers
  1114.  
  1115. FRST    db    0    ;first character of input string
  1116. ARG1    dw    0,0    ;8-byte buffer for digit collection
  1117. ARG1M    db    0
  1118. ARG1X    db    0
  1119. ARG1B    db    0
  1120. ARG1H    db    0
  1121. ARGHH    db    0
  1122. DCPT    db    0    ;decimal point flag and
  1123. DDCT    db    0    ;decimal digit count
  1124. BINXPT    equ    DCPT
  1125. ARG2    dw    0    ;alternate 8-byte buffer
  1126. ARG2B    dw    0
  1127. ARG2M    db    0,0,0
  1128. ARG2H    db    0
  1129. DCXPT    dw    0    ;decimal exponent
  1130. DXSG    db    0    ;flag for sign of decimal exponent
  1131. NSIZ    db    0    ;operand size in bytes
  1132.  
  1133. ;    I-O pointers.
  1134.  
  1135. RX    dw    0000
  1136. RY    dw    0000
  1137. RSEG    dw    0000
  1138.  
  1139. ;    Error flag.
  1140.  
  1141. ER    dw    0000
  1142.  
  1143. ;    Holder for return address from h
  1144.  
  1145. RTADDR    dw    0000
  1146.  
  1147. ;    ======= here is the table of definitions of REC operators =====
  1148.  
  1149. FT    dw    NOOP        ;blank
  1150.     dw    NOOP
  1151.     dw    RECOP        ; [exclm]    binary to hex string
  1152.     dw    HX
  1153.     dw    RECDQ        ; "    quoted expression
  1154.     dw    QU
  1155.     dw    RECOP        ; #    binary to decimal string
  1156.     dw    NS
  1157.     dw    RECOL        ; $    fetch a variable cell
  1158.     dw    VBLE
  1159.     dw    RECOP        ; %    restrict to one byte
  1160.     dw    PE
  1161.     dw    RECOL        ; &    exchange top numeric pair
  1162.     dw    EXCH
  1163.     dw    RECSQ        ; '    quoted expression
  1164.     dw    QU
  1165.     dw    RECLP        ; (
  1166.     dw    NOOP
  1167.     dw    RECRP        ; )
  1168.     dw    NOOP
  1169.     dw    RECOP        ; *    multiply
  1170.     dw    MPY
  1171.     dw    RECOP        ; +    add
  1172.     dw    SUM
  1173.     dw    NOOP        ; ,    separator like space
  1174.     dw    NOOP
  1175.     dw    RECMS        ; -    subtract
  1176.     dw    DIF
  1177.     dw    RECDD        ; .    decimal point
  1178.     dw    NU
  1179.     dw    RECOP        ; /    divide [remainder, quotient]
  1180.     dw    DVD
  1181.     dw    RECDD        ; 0    number
  1182.     dw    NU
  1183.     dw    RECDD        ; 1    number
  1184.     dw    NU
  1185.     dw    RECDD        ; 2    number
  1186.     dw    NU
  1187.     dw    RECDD        ; 3    number
  1188.     dw    NU
  1189.     dw    RECDD        ; 4    number
  1190.     dw    NU
  1191.     dw    RECDD        ; 5    number
  1192.     dw    NU
  1193.     dw    RECDD        ; 6    number
  1194.     dw    NU
  1195.     dw    RECDD        ; 7    number
  1196.     dw    NU
  1197.     dw    RECDD        ; 8    number
  1198.     dw    NU
  1199.     dw    RECDD        ; 9    number
  1200.     dw    NU
  1201.     dw    RECCO        ; :
  1202.     dw    NOOP
  1203.     dw    RECSC        ;    ;
  1204.     dw    NOOP
  1205.     dw    RECOP        ; <    restrict workspace
  1206.     dw    BRA
  1207.     dw    RECPR        ; =    test equality of top pair
  1208.     dw    EQL
  1209.     dw    RECOL        ; >    open workspace
  1210.     dw    KET
  1211.     dw    RECPR        ; ?    test for error report
  1212.     dw    QM
  1213.     dw    RECP1        ; @    execute subroutine
  1214.     dw    AR
  1215.     dw    RECPR        ; A    advance pointer 1
  1216.     dw    UCA
  1217.     dw    RECPR        ; B    retract pointer 1
  1218.     dw    UCB
  1219.     dw    RECOP        ; C    compile
  1220.     dw    UCC
  1221.     dw    RECOP        ; D    delete text
  1222.     dw    UCD
  1223.     dw    RECPL        ; E    equality between WS and PD
  1224.     dw    UCE
  1225.     dw    RECPL        ; F    find specified text
  1226.     dw    UCF
  1227.     dw    RECOP        ; G    fetch a block from memory
  1228.     dw    GA
  1229.     dw    RECPR        ; H    ASCII hex to binary
  1230.     dw    HE
  1231.     dw    RECOL        ; I    insert
  1232.     dw    UCI
  1233.     dw    RECOL        ; J    jump to front
  1234.     dw    UCJ
  1235.     dw    RECOP        ; K    call CP/M, keep (dx), put value
  1236.     dw    CPM
  1237.     dw    RECOL        ; L    erase top of PDL
  1238.     dw    UCL
  1239.     dw    RECPR        ; M    compare PDL and workspace
  1240.     dw    UCM
  1241.     dw    RECPR        ; N    numerical comparison
  1242.     dw    UCN
  1243.     dw    RECPR        ; O    decimal ASCII string to binary
  1244.     dw    UCO
  1245.     dw    RECOP        ; P    put block into buffered memory
  1246.     dw    UCP
  1247.     dw    RECOL        ; Q    put workspace segment on PD
  1248.     dw    UCQ
  1249.     dw    RECOP        ; R    read from keyboard
  1250.     dw    UCR
  1251.     dw    RECOP        ; S    store block in memory
  1252.     dw    SA
  1253.     dw    RECOL        ; T    write on screen
  1254.     dw    UCT
  1255.     dw    RECPR        ; U    search, yielding interval
  1256.     dw    UCU
  1257.     dw    RECPR        ; V    U, including endpoints
  1258.     dw    UCV
  1259.     dw    RECOP        ; W    write on printer
  1260.     dw    UCW
  1261.     dw    RECO1        ; X    call library operator
  1262.     dw    LIBO
  1263.     dw    RECPR        ; Y    recover previous position of p1
  1264.     dw    UCY
  1265.     dw    RECOL        ; Z    pointer 2 to end of text
  1266.     dw    UCZ
  1267.     dw    RECCM        ; [    comment
  1268.     dw    NOOP
  1269.     dw    RECOP        ; \    insert single byte in pair
  1270.     dw    IP
  1271.     dw    RECOP        ; ]
  1272.     dw    NOOP
  1273.     dw    RECOL        ; ^    increment top argument
  1274.     dw    INCR
  1275.     dw    RECOP        ; _    exit to monitor
  1276.     dw    boot
  1277.     dw    RECPR        ; `    true for waiting character
  1278.     dw    CHAW
  1279.     dw    RECPR        ; a    segment forward from p1
  1280.     dw    LCA
  1281.     dw    RECPR        ; b    segment backward from p2
  1282.     dw    LCB
  1283.     dw    RECOP        ; c    create block on PDL
  1284.     dw    BLOK
  1285.     dw    RECPR        ; d    decrement but skip on zero
  1286.     dw    decR
  1287.     dw    RECPR        ; e    extend workspace
  1288.     dw    LCE
  1289.     dw    RECPR        ; f    block fill
  1290.     dw    LCF
  1291.     dw    RECOP        ; g    non-incrementing byte fetch
  1292.     dw    GB
  1293.     dw    RECOP        ; h    store/restore machine state
  1294.     dw    MST
  1295.     dw    RECOP        ; i    input from designated port
  1296.     dw    LCI
  1297.     dw    RECOL        ; j    null interval at p1
  1298.     dw    LCJ
  1299.     dw    RECOP        ; k    call CP/M: no returned values
  1300.     dw    CPML
  1301.     dw    RECOP        ; l    put pz on PDL
  1302.     dw    Lcl
  1303.     dw    RECOP        ; m    set aside top argument
  1304.     dw    LCM
  1305.     dw    RECOL        ; n    recover set-aside argument
  1306.     dw    LCN
  1307.     dw    RECOP        ; o    output from designated port
  1308.     dw    LCO
  1309.     dw    RECOL        ; p    put px, py-px on PDL
  1310.     dw    GXS
  1311.     dw    RECOL        ; q    put p1, p2-p1 on PDL
  1312.     dw    LCQ
  1313.     dw    RECOP        ; r    indirect replacement of address
  1314.     dw    IND
  1315.     dw    RECOP        ; s    store block in memory wrt limit
  1316.     dw    LCS
  1317.     dw    RECOP        ; t    type out indicated interval
  1318.     dw    LCT
  1319.     dw    RECOP        ; u    incrementing byte fetch
  1320.     dw    GBI
  1321.     dw    RECOP        ; v    incrementing byte store
  1322.     dw    SAI
  1323.     dw    RECOP        ; w    store workspace header
  1324.     dw    LCW
  1325.     dw    RECP1        ; x    call library predicate
  1326.     dw    LIBP
  1327.     dw    RECOP        ; y    fetch byte pair to PDL incr org
  1328.     dw    GWI
  1329.     dw    RECOL        ; z    null interval at p2
  1330.     dw    LCZ
  1331.     dw    LBR        ; {    start a definition string
  1332.     dw    NOOP
  1333.     dw    RECOP        ; |    concatinate top two arguments
  1334.     dw    CONC
  1335.     dw    RECOP        ; }    end a definition string
  1336.     dw    NOOP
  1337.     dw    RECOP        ; ~    complement or negate top arg
  1338.     dw    COMP
  1339.     dw    RECOP        ; del
  1340.     dw    NOOP
  1341.  
  1342. ;    Table of often-used combinations to compile as single
  1343. ;    operators or predicates.
  1344.  
  1345. CTB    db    'Ez'        ;to the right if same
  1346.     dw    EZE
  1347.     db    'JZ'        ;span text
  1348.     dw    SPAN
  1349.     db    'z<'        ;null WS at p2
  1350.     dw    ZCL
  1351.     db    'Z>'        ;reopen with p2 at end
  1352.     dw    ZOP
  1353.     db    'Jj'        ;p1 and p2 at p0
  1354.     dw    BEG
  1355.     db    'Z<'        ;restrict from p1 to p3
  1356.     dw    UZCL
  1357.     db    'pG'        ;duplicate PDL argument
  1358.     dw    DUPP
  1359.     db    'ED'        ;delete if same
  1360.     dw    EDE
  1361.     db    'J>'        ;open with p1 at old p0
  1362.     dw    JOP
  1363.     db    'Iz'        ;insert and collapse
  1364.     dw    IZE
  1365.     db    'jJ'        ;p1 and p2 to p0 and p1
  1366.     dw    LJUJ
  1367.     db    '><'        ;reopen and restrict
  1368.     dw    OPCL
  1369.     db    '^^'        ;increase by 2
  1370.     dw    INTW
  1371.     db    'QD'        ;copy and delete
  1372.     dw    QUDE
  1373.     db    'FD'        ;find and delete
  1374.     dw    EFDE
  1375.     db    'nL'        ;lift from PDL complement
  1376.     dw    ENLF
  1377.     db    '&S'        ;exch args and store
  1378.     dw    XSTO
  1379.     db    'LL'        ;lift twice
  1380.     dw    LFTW
  1381.     db    '$r'        ;contents of var cell
  1382.     dw    VREP
  1383.     db    '$S'        ;save in var cell
  1384.     dw    VSTO
  1385.     db    '&L'        ;lift lower
  1386.     dw    XLFT
  1387.     db    'qL'        ;p1 to PDL
  1388.     dw    GTP1
  1389.     db    'J<'        ;restrict from p0
  1390.     dw    JCL
  1391.     db    'I<'        ;insert and restrict
  1392.     dw    ICL
  1393.     db    'TL'        ;type and lift
  1394.     dw    UCTL
  1395.     db    'Qm'        ;copy WS to PDL complement
  1396.     dw    QUEM
  1397.     dw    0000        ;end-of-table marker
  1398.  
  1399. VT    dw    021H dup(?)    ;REC-defined subroutine table & vars.
  1400. STB    dw    05FH dup(?)
  1401. PD    dw    0        ;beginning of PDL
  1402.  
  1403. logo    db    0DH,0AH,'       REC(8086)/ICUAP',0DH,0AH
  1404.     db    'Universidad Autonoma de Puebla',0DH,0AH
  1405.     db    '       February 2, 1986',0DH,0AH,0AH,'$'
  1406.  
  1407. dlst    db    0
  1408.  
  1409. pdlist    ends
  1410.  
  1411. ;    =============
  1412. stack    segment    STACK
  1413.     org    0000H        ;origin of stack segment
  1414. ;    =============
  1415.  
  1416. STKB    dw    0
  1417. STKE    dw    0
  1418. stack    ends
  1419.  
  1420.  
  1421. ;    end
  1422.