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