home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpmug / cpmug007.ark / PILOT.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  67KB  |  1,995 lines

  1. ;    THIS WORK WAS PREPARED UNDER CONTRACT TO THE LISTER HILL NATIONAL CENTER
  2. ;    FOR BIOMEDICAL COMMUNICATIONS, NATIONAL LIBRARY OF MEDICINE, BETHESDA,
  3. ;    MARYLAND BY JOHN A. STARKWEATHER OF THE UNIVERSITY OF CALIFORNIA AT
  4. ;    SAN FRANCISCO.
  5. ;
  6. ;
  7. ;
  8. ;       P I L O T    8080    V E R S I O N   1.2
  9. ;
  10. ;    9/15/77
  11. ;
  12. ;
  13. ;
  14. ORIGN    EQU    06000H        ;ORIGIN OF PROGRAM.
  15. PSTRT    EQU    ORIGN+2E0H    ;START OF PILOT INTERPRETER.
  16. PBUFB    EQU    ORIGN+1000H    ;BEGINNING OF PROGRAM BUFFER.
  17. PBUFE    EQU    ORIGN+1FFFH    ;END OF PROGRAM BUFFER.
  18. LINE    EQU    72        ;MAX INPUT AT STARTUP.
  19. VIDEO   EQU     0FE77H        ;EXTERNAL VIDEO DISPLAY ADDR.
  20. MNTR    EQU     0008H           ;EXTERNAL MONITOR ADDRESS
  21. STKPR    EQU    ORIGN+100H    ;START OF STACK
  22. ;
  23. PORT    EQU    0F6H    ;MDS CONSOLE INPUT PORT
  24. STPORT    EQU    0F7H    ;MDS CONSOLE STATUS PORT
  25. RDA    EQU    02H    ;READ DATA AVAILABLE MASK.
  26. TBE    EQU    01H    ;TRANSMIT BUFFER EMPTY MASK.
  27. ;
  28. INTSRT    EQU    38H    ;MDS INTERRUPT 7 FOR RESTARTING PILOT.
  29. ;
  30.         ORG   INTSRT    ;RESTART PROGRAM BY USE OF INTERRUPT 7.
  31.     ASEG
  32.         JMP   START      ;ENTRY SETS NORMAL I/O
  33. ;
  34.         ;LXI   H,CTV      ;ENTRY TO USE VIDEO OUTPUT
  35.         ;SHLD  CO+1       ;  AT STARTUP
  36.         ;SHLD  LO+1
  37.         ;SHLD  PO+1
  38.         ;JMP   RSTRT
  39. ;CTV:    PUSH  B
  40.         ;MOV   B,C
  41.         ;CALL  VIDEO
  42.         ;POP   B
  43.         ;RET
  44. ;
  45. ; JUMP TABLE FOR I/O ROUTINES
  46. ;   ONLY TTY ROUTINES ARE PROVIDED INTERNALLY
  47. ;
  48.         ORG   STKPR
  49. CI:     JMP   CHI           ;CHAR INPUT  TO   A REG.
  50. CO:     JMP   CHO           ;CHAR OUTPUT FROM C REG.
  51. RI:     JMP   CHI           ;READER INPUT TO  A REG.
  52. LO:     JMP   CHO           ;LIST OUTPUT FROM C REG.
  53. PO:     JMP   CHO           ;PUNCH OUTPUT FROM C REG.
  54. EXIT:   JMP   MNTR          ;RETURN TO MONITOR
  55. EDIT:   JMP   MNTR          ;CALL TO EDITOR
  56. ASCAN:  JMP   BASIC         ;ALTERN INTERPRETER
  57. ;
  58. ; DATA AREAS
  59. TOPP:   DW    0             ;TOP OF PROGRAM STORAGE
  60. HLSAV:  DW    0             ;TEMPORARY POINTER (HL)
  61. HLLSAV: DW    0             ;TEMPORARY POINTER (HL)
  62. HL2SAV: DW    0             ;TEMPORARY POINTER (HL)
  63. DESAV:  DW    0             ;TEMPORARY POINTER (DE)
  64. LLSAV:  DW    0             ;LAST LINE POINTER
  65. RETSAV: DW    0             ;ZERO LEVEL OF STACK
  66.         DW    0             ;LEVEL 1
  67.         DW    0             ;LEVEL 2
  68.         DW    0             ;LEVEL 3
  69.         DW    0             ;LEVEL 4
  70.         DW    0             ;LEVEL 5
  71.         DW    0             ;LEVEL 6
  72.         DW    0             ;LEVEL 7  (TOP)
  73. APTR:   DW    0             ;A STMT POINTER
  74. EPTR:   DW    0             ;ENTRY POINTER
  75. CPTR:   DW    0             ;CHAR POINTER
  76. IPTR:   DW    0             ;INPUT BUFFER POINTER
  77. MPTR:   DW    0             ;M-STMT POINTER
  78. MEMTP:  DW    0             ;LAST MEMORY LOCATION
  79. OUTADR: DW    0             ;CO,LOPO OUTPUT VECTOR
  80. SCANB:  DW   0            ;SCAN BEGINNING ADDR
  81. CHMAX:  DS    1             ;MAXCHARSACCEPTED
  82. LEVEL:    DS    1          ;CURRENT RTURN LEVEL
  83. LNSKP:  DS    1             ;LINE NUMBER SKIP
  84. MBRCH:  DS    1             ;M-BREAK CHAR
  85. SCNT:   DS    1             ;STRING COUNT
  86. TEMP:   DS    1             ;TEMPORARY BINARY VALUE
  87. VARSAV: DS    1             ;VARIABLE SAVED
  88. YNSW:   DS    1             ;YN-SWITCH, 000: NO MATCH
  89. TSAVE:  DS    81            ;T-TEXT AREA
  90. EBUFF:  DS    81            ;ENTRY BUFFER AREA
  91. MSAVE:  DS    81            ;M LIST AREA
  92. LABSAV: DS    12            ;LABEL SAVE AREA
  93. LASTOP: DS    11            ;LAST OP CODE
  94. NVAR:   DS    53            ;NUMERIC VARIABLE STORAGE
  95. WORD:   DS    81            ;WORD AREA
  96. ;
  97. ; START AND TERMINATION OF MAIN PROGRAM
  98. ;   ORG HERE CAN SET BEGINNING OF ROM AREA
  99. ;
  100.         ORG   PSTRT
  101. START:  LXI   SP,STKPR       ;INITIALIZE STACK POINTER
  102.         LXI   H,PBUFE-1     ;INITIALIZE APTR
  103.         SHLD  APTR
  104.         LXI   H,IOJMP       ;SET NORMAL I/O VECTORS
  105.         LXI   D,CI
  106.         MVI   C,24
  107.         CALL  BLKTFR
  108.         JMP   RSTRT
  109. IOJMP:  JMP   CHI           ;COPY OF STD JMP TABLE
  110.         JMP   CHO
  111.         JMP   CHI
  112.         JMP   CHO
  113.         JMP   CHO
  114.         JMP   MNTR
  115.         JMP   MNTR
  116.         JMP   BASIC
  117. ;
  118. RSTRT:  LXI   SP,STKPR       ;INIT STACK ON RESTART
  119.         CALL  INIT          ;INITIALIZE THE REST
  120.         CALL  SCAN          ;SCAN THE BUFFER
  121.         JMP   RSTRT         ;START OVER
  122. ;
  123.         DB    '020677',0DH
  124. ;
  125.         DB    'PILOT-8080, 1.1',0DH
  126. ;
  127. ;
  128. ;
  129. ; INITIALIZE DATA FOR NEW PROGRAM
  130. ;
  131. INIT:   LXI   H,IBUFF       ;RESET INPUT POINTER
  132.         SHLD  IPTR          ;  TO FRONT OF BUFFER
  133.         SHLD  SCANB         ;SET SCAN BEGINNING
  134.         LXI   H,PBUFE       ;SET LAST MEMORY LOC
  135.         SHLD  MEMTP
  136.         CALL  NEWN          ;SET A-POINTER
  137.         CALL  INITV         ;INITIALIZE VARIABLES
  138.         MVI   M,1           ;    SET STOP
  139.         MVI   A,LINE        ;RESET INMAX TO LINE
  140.         STA   CHMAX
  141.         XRA   A             ;ZERO RETURN LEVEL
  142.         STA   LEVEL
  143.         STA   LNSKP         ;ZERO LN NO. SKIP
  144.         LXI   H,CO          ;RESET CONSOLE OUTPUT
  145.         SHLD  OUTADR
  146.         RET
  147. ;
  148. ; SCAN OF INPUT BUFFER
  149. ;   ENTER:   HL=BUFFER ADDR
  150. ;   RETURNS: HL=LAST ADDR, B=LAST CHAR (01)
  151. ;
  152. SCAN:   LHLD  IPTR          ;GET POINTER
  153.         MOV   A,M           ;GET FIRST CHAR
  154.         CPI   1             ;IF END MARKER
  155.         RZ                  ;  THEN RETURN
  156.         CPI   0DH           ;IF NOT END OF LINE
  157.         JNZ   CKEND         ;  THEN CK FOR SOURCE END
  158.         INX   H             ;  ELSE BUMP POINTER
  159.         JMP   SCAN+3        ;  AND CONTINUE
  160. CKEND:  CALL  CNTLN         ;HL=EOL, A=BR CHAR
  161.         CPI   1             ;IF END MARKER
  162.         RZ                  ;  THEN RETURN
  163.         INX   H             ;HL=START OF NEXT LINE
  164.         SHLD  IPTR          ;SAVE THAT ADDR
  165.         DCX   H             ;HL=BREAK CHAR
  166.         CALL  BACKUP        ;RESET HL TO CURRENT LINE
  167.         CALL  SKLN          ;SKIP ANY LN NOS., ETC.
  168.         CALL  GETCH         ;   GET FIRST TEXT CHAR
  169.         CPI   ':'           ;IF COLON
  170.         CZ    CONTIN        ;  THEN CONTINUE SAME OP
  171.         JZ    SCAN          ;  IF CALLED THEN NEXT SCAN
  172.         CPI   '*'           ;IF ASTERISK
  173.         CZ    GETWD         ;  THEN SKIP LABEL
  174.         JZ    SCAN+3        ;IF CALLED THEN RESCAN
  175.         CALL  OPS           ;PROCESS OPERATIONS
  176.         JMP   SCAN
  177. ;
  178. CONTIN: INX   H             ;COLON ADDR + 1
  179.         SHLD  HLSAV         ;SAVE IT
  180.         LXI   H,LASTOP      ;  ADDR LAST OP CODE
  181.         SHLD  LLSAV         ;SAVE OP CODE ADDR
  182.         MVI   B,':'
  183.         CALL  INDX          ;ADDR COLON POS
  184.         CALL  OLDOP         ;USE PART OF OPS
  185.         XRA   A             ; SET RETURN FLAG
  186.         RET
  187. ;
  188. ; OP CODES-- INTERPRET OPERATION
  189. ;   ENTER: HL = FIRST NON-BLANK CHAR IN LINE
  190. ;   RETURNS: RETURN (ZERO) FLAG SET
  191. ;
  192. OPS:    SHLD  LLSAV         ;SAVE OP CODE ADDR
  193.         CALL  SAVOP         ;SAVE OP CODE
  194.         LHLD  LLSAV         ;ADDR OP CODE
  195.         MVI   B,':'         ;  LOOK FOR COLON
  196.         CALL  INDX          ;IF NOT FOUND
  197.         MOV   A,C
  198.         ORA   A
  199.         JZ    ALTSC         ;  THEN TRY ALTERN SCAN
  200.         INX   H             ;COLON ADDR + 1
  201.         SHLD  HLSAV         ;SAVE IT
  202.         DCX   H             ;ADDR POS OF COLON
  203. OLDOP:  DCX   H             ;ADDR POS BEFORE COLON
  204.         CALL  YNCHK         ;IF YN-SW OFF(Y) OR ON(N)
  205.         ORA   A             ;   (A=000)
  206.         RZ                  ;  THEN RETURN
  207.         CALL  VARCHK        ;IF VARIABLE PRESENT < 1
  208.         RZ                  ;  THEN RETURN
  209.         LHLD  LLSAV         ;ADDR OP CODE
  210.         CALL  GETCTL        ;GET THE CONTROL WORD
  211.         CALL  CTLMCH        ;CALL SPECIFIC CONTROL
  212.         CPI   1             ;IF CONTROL FOUND
  213.         RNZ                 ;  THEN RETURN
  214. ALTSC:  LHLD  LLSAV         ;ADDR FIRST CHAR
  215.         CALL  ASCAN         ;TRY ALTERN SCAN
  216.         RZ                  ;IF OK, THEN RETURN
  217.         LHLD  LLSAV         ;ELSE ADDR FIRST CHAR
  218.         SHLD  HLSAV         ;SET POINTER
  219.         CALL  TOP           ;DISPLAY TEXT
  220.         RET
  221. ;
  222. ; TEXT CHECK FOR PRESENCE OF LINE FEEDS,
  223. ;   LINE COUNTS, OR LINE NUMBERS.
  224. ; SETS LNSKP TO NO. OF CHARS TO SKIP BEFORE TEXT
  225. ;
  226. TXTCK:  LXI   H,PBUFF       ;ADDR PROGRAM TEXT
  227.         CALL  CNTLN         ;ADDR CR
  228.         INX   H
  229.         MOV   A,M           ;GET NEXT CHAR
  230.         CPI   0AH           ;IF NOT LF
  231.         JNZ   CKLC          ;  THEN CK FOR LINE COUNT
  232.         CALL  CNTLN         ;ELSE CK ANOTHER LINE
  233.         INX   H
  234.         MOV   A,M
  235.         CPI   0AH           ;IF NOT LF
  236.         JNZ   CKLC          ;  THEN CK FOR LINE COUNT
  237.         LDA   LNSKP         ;ELSE ADD 1 TO LNSKP
  238.         ADI   1
  239.         STA   LNSKP
  240. CKLC:   LXI   H,PBUFF       ;CK FOR LINE COUNT
  241.         CALL  CNTLN         ;ADDR CR
  242.         INX   H             ;  NEXT CHAR
  243.         CALL  SKLN          ;SKIP ANY LF
  244.         MOV   E,M           ;GET POSSIBLE LINE COUNT
  245.         MVI   D,0
  246.         DCX   D             ;DECR IT
  247.         DAD   D             ;ADDR LINE END
  248.         MOV   A,M           ;GET CHAR
  249.         CPI   0DH           ;IF NOT CR
  250.         JNZ   CKLN          ;  THEN CK FOR LINE NO.
  251.         INX   H             ;ELSE CK ANOTHER LINE
  252.         CALL  SKLN
  253.         MOV   E,M
  254.         DCX   D
  255.         DAD   D
  256.         MOV   A,M
  257.         CPI   0DH           ;IF NOT CR
  258.         JNZ   CKLN          ;  THEN CK FOR LINE NOS.
  259.         LDA   LNSKP         ;ELSE ADD 1 TO LNSKP
  260.         ADI   1
  261.         STA   LNSKP
  262. CKLN:   LXI   H,PBUFF+1     ;NOW LOOK FOR LN NOS.
  263.         CALL  CNTLN         ;ADDR CR
  264.         INX   H             ;  NEXT CHAR
  265.         CALL  SKLN          ;SKIP LF OR LN CNT
  266.         MOV   A,M           ;GET CHAR AFTER LN CT
  267.         CALL  NUM           ;IF NOT ASCII NUMBER
  268.         RNZ                 ;  THEN QUIT
  269.         LDA   LNSKP         ;ELSE ADD 4 TO LNSKP
  270.         ADI   4
  271.         STA   LNSKP
  272.         RET
  273. ;
  274. NUM:    CPI   '0'           ;CHECK FOR ASCII NUMBER
  275.         RM                  ;TOO LOW
  276.         CPI   '9'+1
  277.         JM    YNUM
  278.         ORA   H             ;TOO HIGH
  279.         RET
  280. YNUM:   XRA   A             ;OK
  281.         RET
  282. ;
  283. ; SKIP LINE NUMBER AND LINE COUNT
  284. ;    BASED ON VALUE OF LNSKP
  285. ;
  286. SKLN:   LDA   LNSKP         ;GET SKIP COUNT
  287.         ORA   A             ;IF ZERO
  288.         RZ                  ;  THEN RETURN
  289.         INX   H             ;SKIP A CHARACTER
  290.         DCR   A             ;DECR COUNT
  291.         JMP   SKLN+3        ;MORE
  292. ;
  293. ;    CHECK FOR Y OR N CONDITIONS
  294. ; Y AND N FOLLOWING OP CODE
  295. ;      ACT AS A SWITCH ALONG WITH YN-SWITCH
  296. ;   ENTER:   HL = ADDR OF COLON
  297. ;   RETURNS: A = 000 IF NO ACTION REQUIRED
  298. ;                ELSE A = CHAR BEFORE COLON
  299. ;            HL = ADDR OF LAST CHAR BEFORE COLON
  300. ;
  301.  
  302. YNCHK:  CALL  GETLCH        ;GET LAST CHARACTER
  303.         CPI   'Y'           ;IF Y
  304.         JZ    YCHK
  305.         CPI   'N'           ;IF N
  306.         JZ    NCHK
  307.         ORA   A             ; ELSE SET SWITCH ON
  308.         RET                 ;  AND RETURN WITH CHAR
  309. YCHK:   LDA   YNSW          ;IF YN-SWITCH
  310.         ORA   A             ;    SHOWS MATCH
  311.         JZ    DONT          ;  THEN QUIT
  312.         ORA   H             ; ELSE SET SWITCH ON
  313.         RET                 ;  AND RETURN
  314. NCHK:   LDA   YNSW
  315.         ORA   A             ;    SHOWS NO MATCH
  316.         JNZ   DONT          ;  THEN QUIT
  317.         ORA   H             ; ELSE SET SWITCH ON
  318.         RET                 ;  AND RETURN
  319. DONT:   XRA   A             ; SET SWITCH OFF
  320.         RET                 ;  AND RETURN
  321. ;
  322. ;     CHECK FOR NUMERIC VARIABLE CONDITIONS
  323. ; VARIABLE IN PARENTHESES AFTER OP CODE
  324. ;   CAUSES EXECUTION IF VALUE +1 OR MORE
  325. ;    ENTER:   A = LAST CHAR BEFORE COLON
  326. ;    RETURNS: ZERO FLAG OFF IF NO ACTION REQUIRED
  327. ;
  328. VARCHK: CPI   ')'           ;IF VARIABLE PRESENT
  329.         JZ    VCHK          ;  THEN CHECK IT
  330.         ORA   H             ; ELSE SET SWITCH ON
  331.         RET                 ;  AND RETURN
  332. VCHK:   DCX   H             ;DECR POINTER
  333.         DCX   H             ;  TWICE
  334.         MOV   A,M           ;   GET CHAR
  335.         CPI   '('           ;IF PAREN NOT PRESENT
  336.         JNZ   BADFRM        ;  THEN COMPLAIN
  337.         INX   H             ;BUMP POINTER
  338.         MOV   B,M           ;   SAVE CHAR IN B
  339.         CALL  VARMCH        ;LOOK IT UP
  340.         CPI   1             ;IF END MARKER
  341.         JZ    BADFRM        ;  THEN COMPLAIN
  342.         INX   H             ;  ELSE POINT AT VALUE
  343.         MOV   A,M           ;   GET VALUE
  344.         CPI   01
  345.         JM    VOFF          ;  THEN QUIT
  346.         ORA   H             ; ELSE SET SWITCH ON
  347.         RET                 ;  AND RETURN
  348. VOFF:   XRA   A             ; SET SWITCH OFF
  349.         RET                 ;  AND RETURN
  350. ;
  351. BADFRM: LHLD  LLSAV         ;SHOW THE LINE
  352.  
  353.         CALL  TOP+3
  354.         LXI   H,EXPMSG
  355.         CALL  ERROR
  356.         RET
  357. ;
  358. ; VARIABLE MATCH - LOOKUP OF VARIABLE NAME/VALUE LIST
  359. ;    ENTER:   VARIABLE NAME CHAR IN B REGISTER
  360. ;    RETURNS: HL = ADDR OF MATCHED NAME
  361. ;             IF VAR NOT IN LIST THEN A = 01
  362. ;
  363. VARMCH: LXI   H,NVAR
  364.         MOV   A,M
  365.         CPI   1             ;IF LIST END
  366.         RZ                  ;  THEN RETURN
  367.         CMP   B             ;IF MATCH
  368.         RZ                  ;  THEN RETURN
  369.         INX   H             ;  ELSE LOOK AGAIN
  370.         INX   H
  371.         JMP   VARMCH+3
  372. ;
  373. ; CONTROL MATCH- CALLS SPECIFIC CONTROL OPERATIONS
  374. ;   ENTER:   'WORD':CONTROL WORD
  375. ;   RETURNS: IF WORD NOT IN LIST, THEN 01 RETURNED
  376. ;            HL: START OF NEXT WORD
  377. ;
  378. CTLMCH: LXI   D,CTLST       ;  DE=CONTROL LIST ADDR
  379.         CALL  LSTMCH        ;LOOK FOR WORD
  380.         CPI   1             ;IF NOT FOUND
  381.         RZ                  ;  THEN RETURN
  382.         XCHG
  383.         INX   H
  384.         LXI   D,RTRN        ;PUT RETURN ON STACK
  385.         PUSH  D
  386.         MOV   E,M
  387.         INX   H
  388.         MOV   D,M
  389.         PUSH  D             ;CALL ADDR ON STACK
  390.         RET
  391. RTRN:   XRA   A
  392.         RET
  393. ;
  394. ; LIST MATCH - LOOKUP OF WORD/ADDRESS LIST
  395. ;   ENTER:   'WORD' = WORD TO BE FOUND
  396. ;            DE = ADDR OF BEGINNING OF LIST
  397. ;   RETURNS: DE = ADDR OF POINTER (L BYTE)
  398. ;            IF WORD NOT IN LIST THEN A = 01
  399. ;
  400. LSTMCH: LXI   H,WORD        ;  HL=INPUT WORD
  401.         CALL  CMPR          ;COMPARE WORD WITH LIST
  402.         ORA   A             ; IF MATCH
  403.  
  404.         RNZ                 ;  THEN RETURN
  405.         INX   H             ;ELSE HL = DE
  406.         XCHG
  407.         INX   H             ;AND INCR HL TO
  408.         INX   H             ;NEXT LIST ADDR
  409.         INX   H
  410.         MOV   A,M           ;   GET NEXT LIST CHAR
  411.         CPI   1             ;IF END MARKER
  412.         RZ                  ;  THEN RETURN
  413.         XCHG                ;ELSE RESET DE TO NEXT ITEM
  414.         JMP   LSTMCH        ;  AND TRY IT
  415. ;
  416. ; CONTROL LIST - OP CODES AND KEYWORDS
  417. ;
  418. CTLST:  DB    'T',0DH
  419.  
  420.         DW    TOP
  421.         DB    'A',0DH
  422.         DW    AOP
  423.         DB    'M',0DH
  424.         DW    MOP
  425.         DB    'MC',0DH
  426.         DW    MC
  427.         DB    'J',0DH
  428.         DW    JOP
  429.         DB    'R',0DH
  430.         DW    ROP
  431.         DB    'C',0DH
  432.         DW    COP
  433.         DB    'U',0DH
  434.         DW    UOP
  435.         DB    'E',0DH
  436.         DW    EOP
  437.         DB    'Y',0DH
  438.         DW    TOP
  439.         DB    'N',0DH
  440.         DW    TOP
  441.         DB    'LOAD',0DH 
  442. ;LOAD NEW PROGRAM
  443.         DW    LOAD
  444.         DB    'INMAX',0DH 
  445. ;LIMITS CHARS ACCEPTED
  446.         DW    INMAX
  447.         DB    'NEW$',0DH 
  448. ;ERASE $TEXT
  449.         DW    NEWN
  450.         DB    'DP',0DH 
  451.         ;DISPLAY PROGRAM
  452.         DW    DPRG  
  453.         DB    'PRINT',0DH 
  454. ;PRINT PROGRAM
  455.         DW    LPRG
  456.         DB    'SAVE',0DH 
  457. ;SAVE PROGRAM
  458.         DW    SPRG
  459.         DB    'IEP',0DH 
  460. ;INTERPRET EXIST PROG
  461.         DW    IEP
  462.         DB    'BYE',0DH
  463.         DW    EXIT
  464.         DB    'EDIT',0DH
  465.         DW    EDIT
  466. ;COMMON DATAPOINT PILOT CODES NOT IN OPERATION
  467.         DB    'CA',0DH
  468.         DW    CURSR
  469.         DB    'CE',0DH
  470.         DW    CLRE
  471.         DB    'CL',0DH
  472.         DW    CLRL
  473.         DB    'CH',0DH
  474.         DW    CLRH
  475.         DB    'RL',0DH
  476.         DW    ROLL
  477. ;        DB    'WA',0DH
  478. ;        DW    WAIT
  479.     DB    1
  480. ;
  481. CURSR:    MVI C,1BH
  482.     CALL CO
  483.     MVI C,'&'
  484.     CALL CO
  485.     MVI C,61H
  486.     CALL CO
  487.     LHLD HLSAV
  488. CURS1:    MOV A,M
  489.     CPI ','
  490.     JZ CURS3
  491.     CPI 0DH
  492.     JZ CURS4
  493.     MOV C,A
  494. CURS2:    CALL CO
  495.     INX H
  496.     JMP CURS1
  497. CURS3:    MVI C,'r'
  498.     JMP CURS2
  499. CURS4:    MVI C,'C'
  500.     CALL CO
  501.       RET
  502. CLRE:    MVI C,1BH
  503.     CALL CO
  504.     MVI C,'J'
  505.     CALL CO
  506.     RET
  507. CLRL:    MVI C,1BH
  508.     CALL CO
  509.     MVI C,'K'
  510.     CALL CO
  511.     RET
  512. CLRH:    MVI C,1BH
  513.     CALL CO
  514.     MVI C,'H'
  515.     CALL CO
  516.     JMP CLRE
  517. ROLL:    MVI C,1BH
  518.     CALL CO
  519.     MVI C,'S'
  520.     CALL CO
  521.        RET
  522. ;WAIT:   RET
  523. ;
  524. ; INTERPRET EXISTING PROGRAM
  525. ;    STARTS SCAN OF PROGRAM BUFFER
  526. ;
  527. IEP:    LXI   H,PBUFF
  528.         SHLD  IPTR          ;SET POINTER
  529.         SHLD  SCANB         ;  AND SCAN BEGINNING
  530.         CALL  TXTCK         ;CK FOR CHARS TO SKIP
  531.         RET
  532. ;
  533. INMAX:  CALL  NMCTL         ;E = NUMBER CONTROL
  534.         MOV   A,E
  535.         CPI   73            ;LIMIT TO 72
  536.         JM    INMX2
  537.         MVI   A,72
  538.         MOV   E,A
  539. INMX2:  LXI   H,CHMAX       ;  SET INPUT CHAR MAX
  540.         MOV   M,E
  541.         RET
  542. ;
  543. ; CHAR TO BINARY CONVERSION FOR CONTROL ARGUMENTS
  544. ; NUMBER CONTROL - FINDS 1 OR 2 DIGIT NUMBER OR NAME
  545. ;  OF VARIABLE IN NEXT WORD. NEGATIVE VALUES SET TO ZERO.
  546. ;    ENTER:   HLSAV = EXPRESSION ADDRESS
  547. ;    RETURNS: E = BINARY VERSION OF THE NUMBER
  548. ;             A = 0DH IF ALREADY AT END OF LINE
  549. ;             HLSAV = BR CHAR   ADDR
  550. ;
  551. NMCTL:  LHLD  HLSAV         ;EXPRESSION ADDR
  552.         CALL  GETCH         ;GET CHAR
  553.         CPI   0DH           ; IF CR
  554.         RZ                  ;  THEN RETURN
  555.         CALL  GETWD         ;GET NEXT WORD
  556.         DCX   H             ;BACK UP TO BR CHAR
  557.         SHLD  HLSAV         ;SAVE POINTER
  558.         LXI   H,WORD        ;    IN 'WORD'
  559.         CALL  LETTER        ;IF NOT LETTER
  560.         JNZ   CVNUM         ;  THEN CONVERT A NUMBER
  561.         MOV   B,M           ;   ELSE SAVE CHAR IN B
  562.         CALL  VARMCH        ;LOOK IT UP
  563.         CPI   1             ;IF END MARKER
  564.         CZ    BADFRM        ;  THEN COMPLAIN
  565.         RZ                  ;  AND RETURN
  566.         INX   H             ;ELSE POINT AT VALUE
  567.         MOV   E,M           ;   PUT VALUE IN E
  568.         JMP   CVNUM+3       ;  AND QUIT
  569. CVNUM:  CALL  GETNM         ;CONVERT NUMBER
  570.         MOV   A,E           ;      GET VALUE
  571.         ORA   A
  572.         RP                  ;RETURN IF POSITIVE
  573.         MVI   E,0           ;  ELSE SET TO ZERO
  574.         RET
  575. ;
  576. ; JUMP TO LABEL NAME
  577. ;   ENTER:   HLSAV = EXPRESSION FIELD
  578. ;   RETURNS: HL RESET OR MESSAGE
  579. ;
  580. JOP:    LHLD  HLSAV         ;ADDR EXPRESSION
  581.         CALL  GETCH         ;GET FIRST CHAR
  582.         CPI   '*'           ;IF *
  583.         JZ    JOP2          ;  THEN MOVE WORD
  584.         MVI   A,'*'
  585.         STA   WORD          ;ELSE ADD *
  586.         LXI   D,WORD+1      ;  THEN MOVE WORD
  587.         LHLD  HLSAV
  588.         CALL  WDTFR
  589.         JMP   JOP2+3        ;AND CONTINUE
  590. JOP2:   CALL  GETWD         ;GET NEXT WORD
  591.         LHLD  SCANB         ;  START OF SCAN AREA
  592.         CALL  LOOKL         ;LOOK FOR IT
  593.         CPI   1             ;IF LABEL NOT FOUND
  594.         CZ    NTFND         ;  THEN COMPLAIN
  595.         RZ                  ;  AND RETURN
  596.         INX   H
  597.         SHLD  IPTR          ;NEW SCAN POSITION
  598.         RET                 ;RESTART SCAN
  599. ;
  600. ;
  601. NTFND:  LXI   H,WORD        ;  SHOW THE LABEL
  602.         CALL  DSPLY
  603.         LXI   H,BLMSG
  604.         CALL  ERROR
  605.         RET
  606. ;
  607. UOP:    CALL  SAVRET        ;SAVE RETURN POINTER
  608.         JMP   JOP
  609. ;
  610. ; SET A BLOCK OF LENGTH C TO CHAR B
  611. ;
  612. BLKSET: MOV   M,B           ;   STORE ONE CHAR
  613.         INX   H             ;BUMP ADDR
  614.         MOV   A,C           ;   DECR COUNT
  615.         SUI   1
  616.         MOV   C,A           ;      IF COUNT NOT ZERO
  617.         JNZ   BLKSET        ;  THEN STORE ANOTHER
  618.         RET
  619. ;
  620. ; BLANK THE INPUT BUFFER
  621. ;
  622. BLKBF:  LHLD  APTR          ;DE=TOP OF BUFFER
  623.         XCHG
  624.         LXI   H,PBUFF       ;HL=BOTTOM OF BUFFER
  625.         MVI   B,' '
  626. BLKB2:  MOV   M,B
  627.         INX   H
  628.         CALL  ADRCMP
  629.         JNZ   BLKB2
  630.         RET
  631. ;
  632. ; ADDRESS COMPARISON - COMPARES HL + DE
  633. ;    RETURNS: ZERO AND SIGN FLAGS SET AS THOUGH
  634. ;             A CONTAINED HL AND DE WAS COMPARED
  635. ;    CALLED BY BLKBF
  636. ;
  637. ADRCMP: MOV   A,H           ;      GET H
  638.         CMP   D             ;COMPARE D
  639.         RM                  ;IF D > H THEN RETURN
  640.         RNZ                 ;IF D NOT = H THEN RETURN
  641.         MOV   A,L           ;      GET L
  642.         CMP   E             ;COMPARE E
  643.         RET                 ;  AND RETURN
  644. ;
  645. ;    CHARACTER TO BINARY CONVERSION
  646. ; GET A DECIMAL NUMBER-- UP TO 99
  647. ;   ENTER:   HL= CHAR ADDR OF ONE OR TWO DIGIT NUMBER
  648. ;   RETURNS: BINARY NUMBER IN E
  649. ;      IF INPUT NOT NUMERIC, THEN E = 0
  650. ;
  651. GETNM:  MVI   E,0           ;  INIT. OUTPUT VALUE
  652.         INX   H             ;LOOK AT NEXT CHAR
  653.         CALL  BRCHAR        ;IF BREAK CHAR
  654.         JZ    SDIG          ;  THEN SINGLE DIGIT
  655.         CPI   '+'
  656.         JZ    SDIG
  657.         CPI   '-'
  658.         JZ    SDIG
  659.         DCX   H             ;ELSE BACK UP
  660.         MOV   A,M           ;   GET FIRST CHAR
  661.         CPI   '0'           ;LIMIT RANGE
  662.         RM                  ;  TO NUMERALS
  663.         CPI   '9'+1
  664.         RP
  665.         SUI   '0'           ;REMOVE ASCII BIAS
  666.         ADD   A             ;MULT. BY 10
  667.         MOV   E,A           ;        E=A*2
  668.         ADD   A             ;  A*4
  669.         ADD   A             ;  A*8
  670.         ADD   E             ;  A+E=A*10
  671.         MOV   E,A           ;      SAVE IT
  672.         INX   H             ;HL=HL+1
  673. UNITS:  MOV   A,M           ;   GET SECOND CHAR
  674.         CPI   '0'           ;LIMIT RANGE
  675.         RM                  ;  TO NUMERALS
  676.         CPI   '9'+1
  677.         RP
  678.         SUI   '0'           ;REMOVE ASCII BIAS
  679.         ADD   E             ;ADD NEW DIGIT
  680.         MOV   E,A           ;        TO E
  681.         RET
  682. SDIG:   DCX   H             ;BACK UP POINTER
  683.         JMP   UNITS         ;CONVERT UNITS POSITION
  684. ;
  685. ;    BINARY TO CHARACTER CONVERSION
  686. ; PUT BINARY NUMBER IN DECIMAL CHARS -99 TO +99
  687. ;    ENTER:   BINARY NUMBER IN E
  688. ;             HL = CHARACTER AREA
  689. ;    RETURNS: HL = ADDR OF 0DH AFTER RIGHT DIGIT
  690. ;
  691. PUTNM:  MVI   C,0           ;  INITIALIZE C
  692.         MOV   A,E           ;      GET BINARY NUMBER
  693.         ORA   A             ; IF NEGATIVE
  694.         CM    NEG           ;  THEN SHOW MINUS SIGN
  695.         CPI   10            ;IF < 10
  696.         JM    FRMCH         ;  THEN FORM CHAR
  697.         SUI   10            ;  ELSE SUBTR 10
  698.         MOV   E,A           ;        SAVE IN E
  699.         MOV   A,C           ;   INCR TENS COUNT
  700.         ADI   1
  701.         MOV   C,A
  702.         JMP   PUTNM+2       ;  AND LOOP
  703. FRMCH:  MOV   A,C           ;   GET TENS COUNT
  704.         ADI   '0'           ;ADD ASCII BIAS
  705.         CPI   '0'           ;IF CHAR IS 0
  706.         JZ    FRMU          ;  THEN FORM UNITS
  707.         MOV   M,A           ;   STORE THE CHAR
  708.         INX   H             ;BUMP CHAR ADDR
  709. FRMU:   MOV   A,E           ;      GET THE UNITS
  710.         ADI   '0'           ;ADD ASCII BIAS
  711.         MOV   M,A           ;   STORE THE CHAR
  712.         INX   H             ;BUMP POINTER
  713.         MVI   A,0DH         ;   STORE EOL
  714.         MOV   M,A
  715.         RET
  716. ;
  717. NEG:    MVI   A,'-'         ;  STORE MINUS SIGN
  718.         MOV   M,A
  719.         INX   H             ;BUMP CHAR ADDRESS
  720.         XRA   A             ; MAKE BINARY POSITIVE
  721.         SUB   E
  722.         MOV   E,A           ;      SAVE IN E
  723.         RET
  724. ;
  725. ; LOOK FOR *LABEL OR $NAME OF STRING VARIABLE
  726. ;   (LOOKL OR LOOKS)
  727. ;   ENTER: 'WORD'=LABEL TO BE FOUND, HL=SCAN ADDR
  728. ;   RETURNS: HL = ADDR OF BLANK AFTER LABEL
  729. ;            IF LABEL NOT FOUND THEN A = 01
  730. ;
  731. LOOKS:  XRA   A             ;SET TEMP FOR NO SKIPS
  732.         STA   TEMP
  733.         JMP   LOOK
  734. LOOKL:  ORA   H             ;SET TEMP ON FOR SKIPS
  735.         STA   TEMP
  736.         CALL  SKLN          ;SKIP ANY LINE NOS.
  737. LOOK:   CALL  GETCH         ;NEXT CHAR
  738.         CPI   1             ;IF DATA END
  739.         RZ                  ;  THEN RETURN
  740.         CPI   '*'           ;IF *
  741.         JZ    CHK           ;  THEN CHECK THE LABEL
  742.         CPI   '$'           ;IF $
  743.         JZ    CHK           ;  THEN CHECK STRING NAME
  744.         CALL  CNTLN         ;ELSE GO TO NEXT LINE
  745.         INX   H
  746.         LDA   TEMP          ;IF TEMP=0
  747.         ORA   A
  748.         JZ    LOOK          ;  THEN NO SKIPS
  749.         JMP   LOOK-3        ;ELSE SKIP LN NOS.
  750. CHK:    SHLD  HLSAV         ;SAVE POINTER
  751.         CALL  CNTWD         ;C = WORD LENGTH
  752.         MOV   A,C
  753.         CPI   13            ;LIMIT TO 12 CHARS
  754.         JM    MVLAB
  755.         MVI   C,12
  756. MVLAB:  LHLD  HLSAV         ;RETRIEVE POINTER
  757.         LXI   D,LABSAV      ;  DESTIN ADDR
  758.         CALL  BLKTFR        ;MOV   A,BSAV=LABEL
  759.         XCHG                ;HL:DESTIN BR CHAR+1
  760.         DCX   H             ;   DESTIN BR CHAR
  761.         MVI   A,0DH         ;   REPLACE WITH 0DH
  762.         MOV   M,A
  763.         LXI   H,LABSAV
  764.         LXI   D,WORD        ;    WORD ADDR
  765.         CALL  CMPR          ;COMPARE THEM
  766.         ORA   A             ; LOOK AT A REGISTER
  767.         JNZ   LFND          ;IF MATCH THEN LABEL FOUND
  768.         LHLD  HLSAV         ;ELSE RETRIEVE POINTER
  769.         CALL  CNTWD         ;SKIP LABEL
  770.         JMP   LOOK          ;  AND CONTINUE
  771. LFND:   LHLD  HLSAV         ;RETRIEVE POINTER
  772.         CALL  CNTWD         ;SKIP LABEL
  773.         RET                 ;  AND RETURN
  774. ;
  775. ; COMPARE STRINGS X AND Y
  776. ;   ENTER:   HL= X ITEM ADDR, DE= Y ITEM ADDR
  777. ;            BOTH ITEMS TERMINATE IN 0DH
  778. ;   RETURNS: A=0 FOR NO MATCH,
  779. ;            HL AND DE AT 0DH ADDRESS
  780. ;
  781. CMPR:   MOV   A,M           ;   GET X CHAR
  782.         CPI   0DH           ; IF END OF LINE
  783.         JZ    XEND          ;  THEN END OF X ITEM
  784.         MOV   C,A           ;      SAVE X CHAR IN C
  785.         INX   H             ;ADDR Y ITEM
  786.         XCHG
  787.         MOV   A,M           ;   GET Y CHAR
  788.         CPI   0DH           ; IF END OF LINE
  789.         JZ    YENDB         ;  THEN END OF Y ITEM
  790.         CMP   C             ;IF A(Y) NOT= C(X)
  791.         JNZ   NOMCH         ;THEN NO MATCH
  792.         INX   H             ;ADDR NEXT X ITEM
  793.         XCHG
  794.         JMP   CMPR          ;START OVER
  795. XEND:   XCHG                ;ADDR Y ITEM
  796.         MOV   A,M           ;   GET Y CHAR
  797.         CPI   0DH           ; IF END OF LINE
  798.         JZ    MCH           ;  THEN MATCH FOUND
  799.         CALL  CNTWD         ;ADDR Y BR CHAR
  800.         XCHG                ;SET DE
  801.         XRA   A             ;  NOMATCH
  802.         RET
  803. NOMCH:  CALL  CNTWD         ;ADDR Y BR CHAR
  804. YENDB:  XCHG                ;  SET DE
  805.         CALL  CNTWD         ;ADDR X BR CHAR
  806.         XRA   A             ; NO MATCH
  807.         RET
  808. MCH:    XCHG                ;SET DE & HL
  809.         ORA   H             ; MATCH
  810.         RET
  811. ;
  812. ; GET CHARACTER-- SKIPS LEADING BLANKS
  813. ;   ENTER:   HL=SOURCE ADDR
  814. ;   RETURNS: HL=NEXT NON-BLANK ADDR, A=CHAR
  815. ;
  816. GETCH:  MOV   A,M           ;   GET CHARACTER
  817.         CPI   20H           ;IF NOT BLANK
  818.         RNZ                 ;  THEN RETURN
  819.         INX   H             ;  ELSE GET NEXT CHAR
  820.         JMP   GETCH
  821. ;
  822. ; GET LAST CHAR - SCANS BACKWARD, SKIPS BLANKS AND CR'S
  823. ;   ENTER:   HL = STRING ADDR
  824. ;   RETURNS: HL = LAST NON-BLANK CHAR, A = CHAR
  825. ;
  826. GETLCH: MOV   A,M           ;   GET CHARACTER
  827.         CPI   20H           ;IF NOT BLANK
  828.         RNZ                 ;  THEN RETURN
  829.         DCX   H             ;ELSE GET NEXT CHAR
  830.         JMP   GETLCH
  831. ;
  832. ; GET WORD -- UP TO FIRST BREAK CHARACTER
  833. ;            IGNORES LEADING BLANKS
  834. ;   ENTER:   HL=SOURCE ADDR
  835. ;   RETURNS: 'WORD'=SOURCE STRING + 0DH
  836. ;            HL= BR CHAR+1 ADDR, B= BR CHAR
  837. ;            DE= 'WORD' ADDR AFTER 0DH
  838. ;            C = NO OF CHARS MOVED INCL BR CHAR
  839. ;
  840. GETWD:  CALL  GETCH         ;IGNORE LEADING BLANKS
  841.         LXI   D,WORD        ;  DESTIN ADDR
  842.         CALL  WDTFR         ;MOVE IT
  843.         RET
  844. ;
  845. ; COUNT WORD
  846. ;   ENTER:   HL=SOURCE ADDR
  847. ;   RETURNS: HL=BR CHAR ADDR
  848. ;            A,B=BR CHAR, C=COUNT INCL BR CHAR
  849. ;
  850. CNTWD:  MVI   C,1           ;  COUNT=1
  851.         CALL  BRCHAR        ;IF CHAR=BREAK
  852.         RZ                  ;  C=CHAR COUNT
  853.         MOV   A,C           ;   GET COUNT
  854.         ADI   1             ;C=C+1
  855.         MOV   C,A           ;      STORE IT
  856.         INX   H             ;HL=NEXT
  857.         JMP   CNTWD+2       ;NEXT CHAR
  858. ;
  859. ; WORD TRANSFER
  860. ;   MOVES STRING FROM HL TO DE + 0DH ADDED
  861. ;   ENTER:   HL= SOURCE ADDR, DE= DESTIN ADDR
  862. ;   RETURNS: HL= SOURCE ADDR AFTER BR CHAR
  863. ;            DE= DESTIN ADDR AFTER 0DH
  864. ;            B= BR CHAR
  865. ;            C= NO OF CHARS MOVED INCL BR CHAR
  866. ;
  867. WDTFR:  MVI   C,1           ;  INIT COUNT
  868.         CALL  BRCHAR        ;IF BREAK CHAR
  869.         JZ    MVBR          ;  THEN END OF SOURCE
  870.         INX   H             ;HL= DESTIN ADDR
  871.         XCHG
  872.         MOV   M,B           ;   MOVE CHARACTER
  873.         MOV   A,C           ;   INCR COUNT
  874.         ADI   1
  875.         MOV   C,A
  876.         INX   H             ;HL= NEXT SOURCE ADDR
  877.         XCHG
  878.         JMP   WDTFR+2
  879. MVBR:   INX   H             ;HL= DESTIN BR CHAR ADDR
  880.         XCHG
  881.         MVI   A,0DH         ;   REPLACE WITH 0DH
  882.         MOV   M,A
  883.         INX   H             ;HL= SOURCE BR CHAR ADDR+1
  884.         XCHG
  885.         XRA   A             ; SET RETURN FLAG
  886.         RET
  887. ;
  888. ; GET CONTROL WORD IN 'WORD'
  889. ;   REPLACES FINAL Y OR N WITH 0DH
  890. ;   ENTER:   HL = SOURCE ADDR
  891. ;
  892. GETCTL: LXI   D,WORD        ;  DESTIN ADDR
  893.         CALL  WDTFR         ;MOVE WORD
  894.         MOV   A,C           ;   GET COUNT
  895.         CPI   3             ;IF < 3 CHARS MOVED
  896.         RM                  ;  THEN RETURN
  897.         MOV   H,D           ;   ADDR WORD
  898.         MOV   L,E
  899.         DCX   H             ;AVOID COLON
  900.         DCX   H
  901.         CALL  GETLCH        ;GET LAST CHAR
  902.         CPI   'Y'           ;IF Y
  903.         JZ    YNOUT         ;  THEN REMOVE IT
  904.         CPI   'N'           ;IF NOT N
  905.         RNZ                 ;  THEN RETURN
  906. YNOUT:  MVI   A,0DH         ;   REPLACE Y OR N
  907.         MOV   M,A           ;     WITH 0DH
  908.         RET
  909. ;
  910. ; SAVE OP CODE THROUGH COLON IN LASTOP
  911. ;
  912. SAVOP:  MVI   B,':'
  913.         CALL  INDX          ;COUNT CHARS TO COLON
  914.         LHLD  LLSAV         ;ADDR OP CODE
  915.         LXI   D,LASTOP
  916.         CALL  BLKTFR        ;MOVE CHAR STRING
  917.         RET
  918. ;
  919. ; COUNT LINE
  920. ;   ENTER:   HL=SOURCE ADDR
  921. ;   RETURNS: C=CHAR COUNT INCL 0DH OR 01
  922. ;            HL=BREAK POS., A=BR CHAR
  923. ;
  924. CNTLN:  MVI   C,1           ;  COUNT=1
  925.         MOV   A,M           ;   GET CHARACTER
  926.         CPI   0DH           ; IF 0DH
  927.         RZ                  ;   C=CHAR COUNT
  928.         CPI   1             ;IF 01
  929.         RZ                  ;  C=CHAR COUNT
  930.         MOV   A,C           ;   GET COUNT
  931.         ADI   1             ;C=C+1
  932.         MOV   C,A           ;      STORE IT
  933.         INX   H             ;HL=NEXT
  934.         JMP   CNTLN+2       ;NEXT CHAR
  935. ;
  936. ; BACKUP-- DECREMENTS HL BY VALUE OF C-1
  937. ;   ENTER:   HL START VALUE, C=COUNT
  938. ;   RETURNS: NEW HL VALUE
  939. ;
  940. BACKUP: MOV   A,C           ;   GET COUNT
  941.         CPI   1             ;IF COUNT=1
  942.         RZ                  ;  THEN RETURN
  943.         SUI   1             ;C=C-1
  944.         MOV   C,A           ;      STORE C
  945.         DCX   H             ;HL=HL-1
  946.         JMP   BACKUP
  947. ;
  948. ; BREAK CHARACTER SEARCH
  949. ;   ENTER:   HL=CHAR ADDR
  950. ;   RETURNS: A, B = CHARACTER
  951. ;            IF BR CHAR THEN Z FLAG TRUE
  952. ;
  953. BRCHAR: MOV   A,M           ;   GET CHAR
  954.         MOV   B,A           ;   AND SAVE IT
  955.         CPI   ' '           ;CHECK FOR VARIOUS
  956.         RZ                  ;BREAK CHARACTERS
  957.         CPI   0DH           ;   END OF LINE
  958.         RZ
  959.         CPI   ','
  960.         RZ
  961.         CPI   ';'
  962.         RZ
  963.         CPI   ':'
  964.         RZ
  965.         CPI   '.'
  966.         RZ
  967.         CPI   '?'
  968.         RZ
  969.         CPI   21H           ;EXCLAMATION
  970.         RZ
  971.         CPI   '"'           ;DOUBLE QUOTE
  972.         RZ
  973.         CPI   '('           ;L PARENS
  974.         RZ
  975.         CPI   ')'           ;R PARENS
  976.         RZ
  977.         CPI   27H           ;APOSTROPHE
  978.         RZ
  979.         CPI   1             ;END OF LIST
  980.         RET                 ;BR CHAR NOT FOUND
  981. ;
  982. ; INDEX - FIND CHAR POSITION OF MATCHED STRING
  983. ;    ENTER: HLSAV = STRING ADDR, HLLSAVE = SUBSTR ADDR
  984. ;    RETURNS: C = CHAR POS OF MATCH, IF NOMATCH, C=0
  985. ;             HLSAV = STRING ADDR OF FIRST MATCHED CHAR
  986. ;             EPTR = ADDR OF NEXT CHAR AFTER MATCH
  987. ;
  988. INDEX:  XRA   A
  989.         STA   SCNT          ;INIT STRING COUNT
  990. INDE2:  LHLD  HLSAV         ;ADDR STRING
  991.         XCHG                ;DE = STRING ADDR
  992.         LHLD  HLLSAV        ;ADDR SUBSTRING
  993.         MOV   B,M           ;FIRST SUBSTR CHAR IN B
  994.         INX   H             ;ADDR STRING
  995.         XCHG
  996.         CALL  INDX          ;LOOK FOR FIRST CHAR
  997.         MOV   A,C
  998.         ORA   A             ; IF NOT FOUND
  999.         RZ                  ;  THEN RETURN
  1000.         SHLD  HLSAV         ;  ELSE SAVE POINTER
  1001.         LDA   SCNT          ;GET OLD STRING COUNT
  1002.         ADD   C             ;ADD NEW COUNT
  1003.         STA   SCNT          ;  IN SCNT
  1004.         LHLD  HLLSAV        ;ADDR SUBSTR
  1005.         CALL  CNTLN         ;COUNT SUBSTR CHARS
  1006.         MOV   A,C           ;   REDUCE COUNT TO
  1007.         SUI   1             ;  ALPHA CHARS
  1008.         MOV   C,A
  1009.         LXI   D,WORD        ;  MOVE SAME NUMBER OF
  1010.         LHLD  HLSAV         ;  CHARS FROM STRING
  1011.         CALL  BLKTFR        ;  TO 'WORD'
  1012.         SHLD  EPTR          ;SAVE NEXT CHAR ADDR
  1013.         XCHG                ;ADDR END OF 'WORD'
  1014.         MVI   A,0DH         ;   TERMINATE WITH 0DH
  1015.         MOV   M,A
  1016.         LHLD  HLLSAV        ;ADDR SUBSTR
  1017.         XCHG                ;DE = SUBSTR ADDR
  1018.         LXI   H,WORD        ;  ADDR PORTION OF STRING
  1019.         CALL  CMPR          ;COMPARE THEM
  1020.         ORA   A             ; IF FOUND
  1021.         JNZ   SETCNT        ;  THEN SET POSITION COUNT
  1022.         LHLD  HLSAV         ;  ELSE GET STRING POINTER
  1023.         INX   H             ;  BUMP IT
  1024.         SHLD  HLSAV         ;  SAVE IT
  1025.         JMP   INDE2         ;  AND TRY AGAIN
  1026. SETCNT: LXI   H,SCNT        ;  PUT STRING COUNT IN C
  1027.         MOV   C,M
  1028.         RET                 ;    AND RETURN
  1029. ;
  1030. ; INDX - FIND CHARACTER POSITION OF SINGLE LETTER
  1031. ;    ENTER:    HL = STRING ADDR, B= CHAR
  1032. ;    RETURNS:  C = CHAR POS OF MATCH, IF NOMATCH, C=0
  1033. ;              HL = ADDR OF MATCHED CHAR OR EOL
  1034. ;
  1035. INDX:   MVI   C,1           ;  INIT C REGISTER
  1036.         MOV   A,M           ;   GET CHAR
  1037.         CMP   B             ;IF B-CHAR FOUND
  1038.         RZ                  ;  THEN RETURN
  1039.         CPI   0DH           ; IF END OF LINE
  1040.         JZ    ZC            ;  THEN ZERO COUNT
  1041.         MOV   A,C           ;     ELSE
  1042.         ADI   1             ;  BUMP COUNT
  1043.         MOV   C,A
  1044.         INX   H             ;  BUMP ADDR
  1045.         JMP   INDX+2        ;  GO TO NEXT
  1046. ZC:     XRA   A             ; RETURN WITH
  1047.         MOV   C,A           ;        C = 0
  1048.         RET
  1049. ;
  1050. ; SINDX - SPECIAL INDEX FOR POSITION OF $ OR #
  1051. ;    ENTER:   HL = STRING ADDRESS
  1052. ;    RETURNS: BA = $, #, OR 0DH;  C = CHAR POS
  1053. ;             HL = ADDR OF MATCHED CHAR
  1054. ;
  1055. SINDX:  MVI   C,1           ;  INIT C REGISTER
  1056.         MOV   A,M           ;   GET CHAR
  1057.         CPI   '$'           ;IF $
  1058.         RZ                  ;  THEN RETURN
  1059.         CPI   043O          ;IF #
  1060.         RZ                  ;  THEN RETURN
  1061.         CPI   0DH           ; IF EOL
  1062.         RZ                  ;  THEN RETURN
  1063.         MOV   A,C           ;   ELSE
  1064.         ADI   1             ;BUMP COUNT
  1065.         MOV   C,A
  1066.         INX   H             ;BUMP ADDR
  1067.         JMP   SINDX+2       ;GO TO NEXT
  1068. ;
  1069. ; LETTER TESTS WHETHER CHARACTER IS UPCASE A-Z
  1070. ;    ENTER:   HL = ADDR OF CHAR
  1071. ;    RETURNS: ZERO FLAG TRUE IF IT IS
  1072. ;             B = CHARACTER
  1073. ;
  1074. LETTER: MOV   A,M           ;   GET CHAR
  1075.         MOV   B,M           ;   SAVE IN B
  1076.         CPI   41H           ;CHECK RANGE
  1077.         JM    NOTL          ;TOO LOW?
  1078.         CPI   5AH
  1079.         JP    NOTL          ;TOO HIGH?
  1080.         XRA   A             ;   ELSE RESET ZERO FLAG
  1081.         RET                 ;  AND RETURN IF LETTER
  1082. NOTL:   ORA   H             ; RETURN IF NOT LETTER
  1083.         RET
  1084. ;
  1085. ; SETUP GETS CHAR COUNT AND SETS ADDR FOR TEXT MOVES
  1086. ;
  1087. SETUP:  CALL  CNTLN         ;C=CHAR COUNT
  1088.         MOV   B,C           ;   SAVE COUNT
  1089.         CALL  BACKUP        ;RESET HL
  1090.         MOV   C,B           ;   RESET COUNT
  1091.         RET
  1092. ;
  1093. ; T OPERATION--DISPLAY 'T' STATEMENT
  1094. ;   ENTER:   HLSAV= FIRST CHAR OF T EXPRESSION FIELD
  1095. ;
  1096. TOP:    LHLD  HLSAV         ;RETRIEVE POINTER
  1097.         SHLD  CPTR          ;SAVE CHAR POINTER
  1098.         SHLD  LLSAV         ;SAVE FIRST CHAR ADDR
  1099.         LXI   H,TSAVE       ;  DESTIN START ADDR
  1100.         SHLD  DESAV         ;SAVE DESTIN ADDR
  1101.         XCHG                ;AND KEEP IN DE
  1102. TMORE:  LHLD  CPTR          ;GET CHAR POINTER
  1103.         CALL  SINDX         ;LOOK FOR $ OR #
  1104.         CPI   '$'           ;IF $ FOUND
  1105.         JZ    GETXT         ;  THEN GET LABELED TEXT
  1106.         CPI   043O          ;IF # FOUND
  1107.         JZ    GETNUM        ;  THEN GET NUMBER
  1108.         JMP   TMOVE         ;ELSE MOVE REST OF TEXT
  1109. GETXT:  CALL  INSERT        ;INSERT TEXT
  1110.         CPI   1             ;IF FOUND (A NOT 01)
  1111.         JNZ   TMORE         ;  THEN CONTINUE
  1112.         LXI   D,TSAVE       ;  ELSE DISPLAY THE LINE
  1113.         LHLD  LLSAV
  1114.         JMP   TALL
  1115. GETNUM: CALL  INSNUM        ;INSERT NUMBER
  1116.         JMP   GETXT+3       ;  AND SEE IF FOUND
  1117. TMOVE:  LHLD  DESAV         ;DESTIN ADDR
  1118.         XCHG
  1119.         LHLD  CPTR          ;ADDRESS INPUT
  1120. TALL:   CALL  SETUP         ;C = CHAR COUNT
  1121.         CALL  BLKTFR        ;MOVE T-TEXT
  1122.         MVI   A,0DH         ;   TERMINATE
  1123.         XCHG
  1124.         MOV   M,A
  1125.         LXI   H,TSAVE       ;  ADDRESS TEXT
  1126.         CALL  DSPLY         ;DISPLAY T STATEMENT
  1127.         XRA   A             ; SET RETURN FLAG
  1128.         RET
  1129. ;
  1130. ; INSERT NUMERIC VALUE INTO T-STATEMENT
  1131. ;    ENTER:   C = POSITION OF '#'
  1132. ;    RETURNS: TSAVE CONTAINS ASSEMBLED T-TEXT
  1133. ;             IF LABEL NOT FOUND, THEN A = 01
  1134. ;
  1135. INSNUM: MOV   A,C           ;   GET POSITION OF #
  1136.         SUI   1             ;REDUCE COUNT BY 1
  1137.         JZ    VBL           ;IF 0 THEN GET VARIABLE
  1138.         MOV   C,A
  1139.         LHLD  DESAV         ;DESTIN ADDR
  1140.         XCHG
  1141.         LHLD  CPTR          ;GET CHAR POINTER
  1142.         CALL  BLKTFR        ;MOVE FRONT OF TEXT
  1143. VBL:    MOV   B,H
  1144.         MOV   C,L
  1145.         XCHG
  1146.         SHLD  DESAV         ;SAVE DESTIN POINTER
  1147.         MOV   H,B           ;   GET CHAR POINTER
  1148.         MOV   L,C
  1149.         INX   H             ;BUMP TO VAR NAME
  1150.         MOV   C,M           ;   SAVE NAME IN C
  1151.         INX   H             ;BUMP ADDR
  1152.         SHLD  CPTR          ;SAVE CHAR POINTER
  1153.         MOV   B,C           ;   PUT VAR NAME IN B
  1154.         CALL  VARMCH        ;LOOK UP VAR NAME
  1155.         CPI   1             ;IF NOT FOUND (A = 01)
  1156.         RZ                  ;  THEN RETURN
  1157.         INX   H             ;ELSE POINT AT VALUE
  1158.         MOV   E,M           ;   GET VALUE IN E
  1159.         LXI   H,WORD        ;  PUT DIGITS IN WORD
  1160.         CALL  PUTNM
  1161.         LHLD  DESAV         ;DESTIN ADDR
  1162.         XCHG
  1163.         LXI   H,WORD        ;  DIGIT CHAR ADDR
  1164.         CALL  SETUP         ;C = CHAR COUNT+1
  1165.         MOV   A,C
  1166.         SUI   1
  1167.         MOV   C,A           ;      C = CHAR COUNT
  1168.         CALL  BLKTFR        ;MOVE DIGITS
  1169.         XCHG
  1170.         SHLD  DESAV         ;SAVE DESTIN ADDR
  1171.         XRA   A             ; SET RETURN FLAG
  1172.         RET
  1173. ;
  1174. ; INSERT LABELED TEXT INTO T-STATEMENT
  1175. ;    ENTER:   C = POSITION OF '$'
  1176. ;    RETURNS: TSAVE CONTAINS ASSEMBLED T-TEXT
  1177. ;             IF LABEL NOT FOUND, THEN A = 01
  1178. ;
  1179. INSERT: MOV   A,C           ;   GET POSITION COUNT
  1180.         SUI   1             ;REDUCE COUNT BY 1
  1181.         JZ    LBL           ;IF 0 THEN POINT TO LABEL
  1182.         MOV   C,A
  1183.         LHLD  DESAV         ;DESTIN ADDR
  1184.         XCHG
  1185.         LHLD  CPTR          ;GET CHAR POINTER
  1186.         CALL  BLKTFR        ;MOVE FRONT OF TEXT
  1187. LBL:    MOV   B,H           ; SAVE CHAR POINTER IN BC
  1188.         MOV   C,L
  1189.         XCHG
  1190.         SHLD  DESAV         ;SAVE DESTIN POINTER
  1191.         MOV   H,B           ;   GET CHAR POINTER
  1192.         MOV   L,C
  1193.         CALL  GETWD         ;GET LABEL
  1194.         DCX   H             ;ADDR BR CHAR
  1195.         SHLD  CPTR          ;SAVE CHAR POINTER
  1196.         LHLD  APTR          ;HL = START OF LIST
  1197.         INX   H
  1198.         CALL  LOOKS         ;LOOK FOR STRING NAME
  1199.         CPI   1             ;IF NOT FOUND (A = 01)
  1200.         RZ                  ;  THEN RETURN
  1201.         CALL  GETA          ;  ELSE GET A-TEXT
  1202.         RET
  1203. ;
  1204. ; GET A-TEXT POINTED TO BY MATCHED LABEL
  1205. ;    ENTER:   HL = BLANK AFTER MATCHED LABEL
  1206. ;             DESAV = DESTIN ADDRESS
  1207. ;    RETURNS: A-TEXT MOVED TO DESTINATION
  1208. ;             DESAV = NEXT DESTIN ADDRESS
  1209. ;
  1210. GETA:   INX   H             ;ADDR FIRST A-CHAR
  1211.         MOV   B,H           ;   BC = A-TEXT ADDR
  1212.         MOV   C,L
  1213.         LHLD  DESAV         ;DESTIN ADDR
  1214.         XCHG
  1215.         MOV   H,B           ;   HL = A-TEXT ADDR
  1216.         MOV   L,C
  1217.         CALL  SETUP         ;C = CHAR COUNT
  1218.         MOV   A,C           ;   REDUCE COUNT TO
  1219.         SUI   1             ;  EXCLUDE MOVE OF 0DH
  1220.         MOV   C,A
  1221.         CALL  BLKTFR        ;MOVE A-TEXT
  1222.         XCHG
  1223.         SHLD  DESAV         ;SAVE DESTIN POINTER
  1224.         XRA   A             ; SET RETURN FLAG
  1225.         RET
  1226. ;
  1227. ; A OPERATION-- ACCEPT INPUT
  1228. ;   ENTER:    HLSAV = ADDR AFTER COLON
  1229. ;   RETURNS:  INPUT IN EBUFF
  1230. ;   'CTL Z' ALLOWS SINGLE STATEMENT EXECUTION OR QUIT
  1231. ;
  1232. AOP:    LHLD  HLSAV         ;ADDR EXPRESSION
  1233.         CALL  GETCH         ;GET FIRST CHAR
  1234.         CPI   '$'           ;IF NOT $
  1235.         JNZ   NIN           ;  THEN LOOK FOR #
  1236.         LXI   D,LABSAV      ;  ELSE ADDR DESTIN
  1237.         CALL  WDTFR         ;  SAVE THE LABEL
  1238.         CALL  ENTRY         ;GET THE ENTRY
  1239.         CALL  ASTORE        ;  STORE IT
  1240.         RET                 ;  THEN EXIT
  1241. NIN:    CPI   043O          ;IF NOT #
  1242.         JNZ   CENT          ;  THEN CALL ENTRY
  1243.         INX   H             ;ELSE ADDR VARIABLE
  1244.         MOV   A,M           ;   GET THE NAME
  1245.         STA   VARSAV        ;AND SAVE IT
  1246.         CALL  ENTRY         ;GET THE ENTRY
  1247.         CALL  CKNUM         ;REQUIRE NUMERIC
  1248.         CALL  NSTORE        ;  STORE THE NUMBER
  1249.         RET                 ;THEN EXIT
  1250. CENT:   CALL  ENTRY
  1251.         RET
  1252. ;
  1253. ENTRY:  CALL  KEYIN         ;GET ONE LINE IN EBUFF
  1254.         LXI   H,EBUFF       ;IF ENTRY NOT CTL Z
  1255.         MOV   A,M
  1256.         CPI   1AH
  1257.         RNZ                 ;THEN RETURN
  1258.         INX   H             ;ELSE BUMP POINTER
  1259.         MOV   A,M           ;GET CHAR
  1260.         CPI   0DH           ;IF CR
  1261.         JZ    RSTRT         ;  THEN RESTART
  1262.         CALL  OPS           ;ELSE DO IMMED OP
  1263.         JMP   ENTRY         ;  AND ACCEPT MORE INPUT
  1264. ;
  1265. CKNUM:  CPI   '0'           ;CHECK FOR NUMBER
  1266.         JM    NERR          ;TOO LOW
  1267.         CPI   '9'+1
  1268.         RM                  ;MUST BE NUMBER
  1269. NERR:   LXI   H,NMSG        ;OUT OF RANGE
  1270.         CALL  ERROR         ;SEND MESSAGE
  1271.         CALL  ENTRY         ;TRY AGAIN
  1272.         JMP   CKNUM
  1273. ;
  1274. ; A ITEM STORE - STORAGE OF LABELED TEXT FROM ENTRY
  1275. ;    FROM TOP OF INPUT BUFFER AREA AND SETS POINTER
  1276. ;
  1277. ASTORE: LXI   H,EBUFF       ;  SOURCE ADDR
  1278.         CALL  CNTLN         ;C = CHAR COUNT
  1279.         MOV   B,C           ;   DUPL COUNT IN B
  1280.         LHLD  APTR          ;LAST A-ADDR
  1281.         CALL  DECA          ;BACK UP DESTIN ADDRESS
  1282.         MOV   A,C           ;   IF CHAR COUNT = 0
  1283.         ORA   A
  1284.         RZ                  ;  THEN RETURN
  1285.         LXI   H,EBUFF       ;  SOURCE ADDR
  1286.         CALL  BLKTFR        ;MOVE TEXT
  1287.         LXI   H,LABSAV      ;  ADDR LABEL
  1288.         CALL  CNTLN         ;C = CHAR COUNT
  1289.         MOV   B,C           ;   DUPL COUNT IN B
  1290.         LHLD  APTR          ;GET A-POINTER
  1291.         CALL  DECA          ;BACK UP ADDR
  1292.         MOV   A,C           ;   IF CHAR COUNT = 0
  1293.         ORA   A
  1294.         RZ                  ;  THEN RETURN
  1295.         LXI   H,LABSAV      ;  SOURCE ADDR
  1296.         CALL  BLKTFR        ;MOVE THE LABEL
  1297.         MOV   L,E           ;   ADDR A-TEXT
  1298.         MOV   H,D
  1299.         DCX   H             ;BACK UP ONE CHAR
  1300.         MVI   A,' '         ;AND SET
  1301.         MOV   M,A           ;     BLANK THERE
  1302.         RET
  1303. ;
  1304. ; DECREMENT ADDRESS FOR TEXT STORAGE
  1305. ;    ENTER:  HL = LAST (LOWEST) ADDRESS USED (01)
  1306. ;            B & C = CHAR COUNT IN WORD TO BE MOVED
  1307. ;    RETURNS:DE = DESTIN ADDR,  C = CHAR COUNT
  1308. ;       APTR POINTS AT STOP(01) BELOW LIST
  1309. ;
  1310. DECA:   MOV   E,L           ;DESTIN ADDR IN DE
  1311.         MOV   D,H
  1312.         DCX   H             ;DECR POINTER
  1313.         MOV   A,M           ;   GET CHARACTER
  1314.         CPI   1             ;IF 01 (END OF SPACE)
  1315.         JZ    STOVF         ;  THEN STORAGE OVERFLOW
  1316.         MOV   A,B           ;      DECR COUNT
  1317.         SUI   1
  1318.         MOV   B,A
  1319.         JNZ   DECA          ;BACK UP AGAIN?
  1320.         SHLD  APTR          ;SAVE A-POINTER
  1321.         MVI   M,1           ;SET STOP
  1322.         RET
  1323. ;
  1324. STOVF:  LXI   H,NRMSG       ;  COMPLAIN OF OVERFLOW
  1325.         CALL  ERROR
  1326.         MVI   C,0           ;  SET CHAR COUNT = 0
  1327.         RET
  1328. ;
  1329. ; NUMBER STORAGE - STORAGE OF NUMERIC VALUE FROM ENTRY
  1330. ;             AS VALUE OF VARIABLE NAME IN A-STATEMENT
  1331. ;
  1332. NSTORE: LXI   H,EBUFF       ;  SOURCE ADDR
  1333.         CALL  GETCH         ;ADDR 1ST CHAR
  1334.         CALL  GETNM         ;GET THE NUMBER
  1335.         LXI   H,VARSAV      ;  GET THE NAME IN B
  1336.         MOV   B,M
  1337.         CALL  VARMCH        ;LOOK IT UP
  1338.         CPI   1             ;IF END MARKER
  1339.         CZ    BADFRM        ;THEN COMPLAIN
  1340.         RZ                  ;  AND RETURN
  1341.         INX   H             ;  ELSE BUMP TO NEXT
  1342.         MOV   M,E
  1343.         RET
  1344. ;
  1345. ; M OPERATION - MOVING WINDOW STRING MATCH
  1346. ;    COMPARE ITEMS IN LIST WITH LAST INPUT
  1347. ;      M-ITEMS HAVE MULTIPLE BLANKS REDUCED TO ONE
  1348. ;      INPUT HAS BLANK ADDED AT EACH END AND
  1349. ;      MULTIPLE BLANKS REDUCED TO ONE.
  1350. ; ENTER: HLSAV = ADDR AFTER LAST COLON, INPUT IN EBUFF
  1351. ; RETURNS: YNSW = 0 IF MATCH NOT FOUND WITH LAST ENTRY
  1352. ;
  1353. MC:     LXI   H,MBRCH       ;SET BR CHAR
  1354.         MVI   M,'^'         ;  TO CARET (SHIFT N)
  1355.         JMP   MOP1
  1356. MOP:    LXI   H,MBRCH       ;SET BR CHAR TO COMMA
  1357.         MVI   M,','
  1358. MOP1:   LHLD  HLSAV         ;ADDR EXPRESSION FIELD
  1359.         SHLD  MPTR          ;INIT M-POINTER
  1360. NEXTM:  CALL  MMOV          ;MSAVE = M-ITEM
  1361.         LHLD  MPTR          ;ADDR M-ITEM
  1362.         SHLD  HLSAV
  1363.         CALL  SQUEZ         ;REDUCE MULTIPLE BLANKS
  1364.         LXI   H,EBUFF
  1365.         SHLD  HLSAV         ;HLSAV = STRING ADDR
  1366.         CALL  PAD           ;ADD BLANKS AT EACH END
  1367.         CALL  SQUEZ         ;REDUCE MULTIPLE BLANKS
  1368.         LXI   H,EBUFF       ;  PUT EBUFF ADDR
  1369.         SHLD  HLSAV         ;  IN HLSAV
  1370.         LXI   H,MSAVE       ;  PUT MSAVE ADDR
  1371.         SHLD  HLLSAV        ; IN HLLSAV
  1372.         CALL  INDEX         ;LOOK FOR M-ITEM
  1373.         MOV   A,C
  1374.         ORA   A             ; IF ITEM FOUND
  1375.         CNZ   SWY           ;  THEN SET SWITCH YES
  1376.         RNZ                 ;  AND RETURN
  1377.         LHLD  MPTR          ;RETRIEVE M-POINTER
  1378.         DCX   H             ;ADDR BR CHAR
  1379.         MOV   A,M           ;   IF END OF LINE
  1380.         CPI   0DH
  1381.         JZ    MDONE         ;  THEN QUIT
  1382.         INX   H             ;ADDR NEXT CHAR
  1383.         MOV   A,M           ;   IF END OF LINE
  1384.         CPI   0DH
  1385.         JZ    MDONE         ;  THEN QUIT
  1386.         JMP   NEXTM         ;ELSE MORE M-ITEMS
  1387. MDONE:  CALL  SWN           ;SET SWITCH NO
  1388.         RET
  1389. ;
  1390. SWY:    ORA   H             ; SET YN SWITCH YES
  1391.         STA   YNSW
  1392.         RET
  1393. ;
  1394. SWN:    XRA   A             ; SET YN SWITCH NO
  1395.         STA   YNSW
  1396.         RET
  1397. ;
  1398. ; M-MOVE: MOVE M-ITEM TO MSAVE
  1399. ;   ITEMS ARE SEPARATED BY COMMA OR TERMINATED BY 0DH
  1400. ;   ENTER:   MPTR = M-ITEM ADDRESS
  1401. ;   RETURNS: HL & MPTR = NEXT M-ITEM ADDR
  1402. ;            B = BR CHAR
  1403. ;
  1404. MMOV:   LHLD  MPTR          ;GET M-POINTER
  1405.         LXI   D,MSAVE       ;  DESTIN ADDR
  1406. MMOV2:  CALL  MBR           ;IF BR CHAR OR EOL
  1407.         JZ    SMOV          ;  THEN STOP THE MOVE
  1408.         INX   H
  1409.         XCHG                ;HL = DESTIN ADDR
  1410.         MOV   M,B           ;   MOVE CHAR
  1411.         INX   H
  1412.         XCHG                ;HL = NEXT SOURCE ADDR
  1413.         JMP   MMOV2         ;CHECK THE NEXT CHAR
  1414. SMOV:   INX   H
  1415.         XCHG                ;HL = DESTIN BR CHAR ADDR
  1416.         MVI   A,0DH         ;   PUT AN 0DH THERE
  1417.         MOV   M,A
  1418.         INX   H
  1419.         XCHG                ;HL = NEXT M-ITEM ADDR
  1420.         SHLD  MPTR          ;SAVE M-POINTER
  1421.         RET
  1422. ;
  1423. ; M-BREAK CHAR BETWEEN ITEMS
  1424. ;    ENTER:   HL = CHAR ADDR
  1425. ;    RETURNS: A,B = CHAR.  IF BR CHAR THEN Z FLAG TRUE
  1426. ;
  1427. MBR:    MOV   A,M           ;   GET CHAR
  1428.         MOV   B,A           ;   SAVE IT
  1429.         CPI   0DH           ; IF EOL
  1430.         RZ                  ;  THEN RETURN
  1431.         LDA   MBRCH         ;GET CURRENT BR CHAR
  1432.         CMP   B
  1433.         RET
  1434. ;
  1435. ; PAD ADDS A BLANK TO EACH END OF A STRING
  1436. ;   ENTER:   HLSAV = STRING ADDRESS
  1437. ;
  1438. PAD:    LXI   H,WORD
  1439.         MVI   A,' '         ;  SET BLANK AT FRONT OF
  1440.         MOV   M,A
  1441.         INX   H             ;DE = DESTIN ADDR
  1442.         XCHG
  1443.         LHLD  HLSAV         ;GET SOURCE ADDR
  1444.         CALL  CNTLN         ;C = CHAR COUNT
  1445.         LHLD  HLSAV         ;GET SOURCE ADDR
  1446.         CALL  BLKTFR        ;MOVE TEXT
  1447.         XCHG                ;ADDR NEW TEXT END
  1448.         DCX   H             ;SET BLANK AT
  1449.         MVI   A,' '         ;    END OF
  1450.         MOV   M,A           ;     TEMP STRING
  1451.         INX   H             ;SET EOL
  1452.         MVI   A,0DH
  1453.         MOV   M,A
  1454.         LHLD  HLSAV         ;MOVE NEW STRING
  1455.         XCHG                ;  TO ORIGINAL
  1456.         LXI   H,WORD        ;    LOCATION
  1457.         CALL  CNTLN
  1458.         LXI   H,WORD
  1459.         CALL  BLKTFR
  1460.         RET
  1461. ;
  1462. ; SQUEZ REDUCES MULTIPLE BLANKS TO A SINGLE BLANK
  1463. ;   ENTER:   HLSAV = STRING ADDRESS
  1464. ;
  1465. SQUEZ:  LHLD  HLSAV         ;ADDR STRING
  1466.         SHLD  HLLSAV        ;SAVE POINTER
  1467.         MOV   A,M           ;   GET CHAR
  1468. CKEOL:  CPI   0DH           ; IF EOL
  1469.         RZ                  ;  THEN RETURN
  1470.         CPI   ' '           ;IF BLANK
  1471.         JZ    CKNC          ;  THEN CHECK NEXT CHAR
  1472.         INX   H             ;ELSE BUMP ADDR
  1473.         JMP   SQUEZ+3       ;  AND CONTINUE
  1474. CKNC:   INX   H             ;IF NEXT CHAR IS
  1475. CKNC1:  MOV   A,M           ;     NOT BLANK
  1476.         CPI   ' '           ;  THEN CHECK IF EOL
  1477.         JNZ   CKEOL
  1478.         SHLD  HLLSAV        ;ELSE SAVE ADDRESS
  1479.         CALL  SHIFT         ;  REMOVE A BLANK
  1480.         LHLD  HLLSAV        ;  RETRIEVE ADDRESS
  1481.         JMP   CKNC1         ;  AND CONTINUE
  1482. ;
  1483. ; SHIFT STRING CHARS LEFT WITH LOSS OF FIRST CHAR
  1484. ;   ENTER:   HL = ADDR OF STRING
  1485. ;   RETURNS: HL = ADDR OF 0DH
  1486. ;
  1487. SHIFT:  INX   H             ;ADDR NEXT CHAR
  1488.         MOV   B,M           ;   GET IT IN B
  1489.         DCX   H             ;MOVE IT
  1490.         MOV   M,B
  1491.         MOV   A,M
  1492.         CPI   0DH           ; IF IT WAS EOL
  1493.         RZ                  ;  THEN RETURN
  1494.         INX   H             ;  ELSE MOVE ANOTHER
  1495.         JMP   SHIFT
  1496. ;
  1497. ; C OPERATION:  COMPUTE WITH TEXT OF STATEMENT
  1498. ;    LIMITED TO: X = NN  (NN = INTEGER -99 TO +99)
  1499. ;                OR X = X + NN  OR X = X - NN
  1500. ;                OR X = X + X   OR X = X - X
  1501. ;      WHERE X = SINGLE LETTER VARIABLE NAME A-Z
  1502. ;           FIRST LETTER ONLY OF LONGER NAME GETS USED
  1503. ;    ENTER:   HLSAV = ADDR OF EXPRESSION FIELD
  1504. ;
  1505. COP:    LHLD  HLSAV         ;ADDR EXPRESSION FIELD
  1506.         MVI   B,'='         ;  LOOK FOR EQUAL SIGN
  1507.         CALL  INDX
  1508.         MOV   A,C
  1509.         ORA   A             ; IF NOT PRESENT
  1510.         JZ    EXMSG         ;  THEN COMPLAIN
  1511.         INX   H             ;BUMP POINTER
  1512.         CALL  GETCH         ;GET THE CHAR
  1513.         CPI   '-'           ;IF NOT MINUS SIGN
  1514.         JNZ   CGVAL         ;  THEN GET THE VALUE
  1515.         SHLD  HLLSAV        ;SAVE THE POINTER
  1516.         XRA   A
  1517.         STA   TEMP          ;SET TEMP = 0
  1518.         LHLD  HLLSAV        ;RETRIEVE POINTER
  1519.         JMP   SUBV          ;  AND SUBTRACT
  1520. CGVAL:  CALL  GVALUE        ;GET THE VALUE
  1521.         LXI   H,TEMP        ;  SAVE IT
  1522.         MOV   M,E
  1523.         LHLD  CPTR          ;RETRIEVE CHAR POINTER
  1524.         INX   H             ;BUMP POINTER
  1525.         CALL  GETCH         ;GET CHAR
  1526.         CPI   0DH           ; IF END OF LINE
  1527.         JZ    AVAL          ;  THEN ASSIGN VALUE
  1528.         CPI   '-'           ;IF MINUS
  1529.         JZ    SUBV          ;  THEN SUBTRACT VALUE
  1530.         CPI   '+'           ;IF PLUS
  1531.         JZ    ADDV          ;  THEN ADD VALUE
  1532.         CALL  GVALUE        ;ELSE GET VALUE
  1533.         JMP   AVAL          ;ASSIGN VALUE
  1534. ADDV:   INX   H             ;BUMP POINTER
  1535.         CALL  GVALUE        ;GET THE VALUE
  1536.         LDA   TEMP          ;GET OLD VALUE
  1537.         ADD   E             ;ADD VALUES
  1538.         CPI   100           ;IF > 99
  1539.         JP    OVMSG         ;  THEN COMPLAIN
  1540.         MOV   E,A           ;      ELSE FORM NEW VALUE
  1541.         JMP   AVAL          ;ASSIGN VALUE
  1542. SUBV:   INX   H             ;BUMP POINTER
  1543.         CALL  GVALUE        ;GET THE VALUE
  1544.         LDA   TEMP          ;GET OLD VALUE
  1545.         SUB   E             ;SUBTRACT VALUES
  1546.         CPI   9DH           ;IF >= -99
  1547.         JP    AVAL-1        ;  THEN CONTINUE
  1548.         CPI   100           ;IF > 99
  1549.         JP    UNMSG         ;  THEN COMPLAIN
  1550.         MOV   E,A
  1551. AVAL:   CALL  ASSIGN
  1552.         RET
  1553. ;
  1554. EXMSG:  CALL  TOP           ;SHOW THE BAD EXPR
  1555.         LXI   H,EXPMSG
  1556.         CALL  ERROR
  1557.         RET
  1558. ;
  1559. OVMSG:  MVI   E,99          ;  SET VALUE TO 99
  1560.         CALL  ASSIGN
  1561.         CALL  TOP           ;SHOW THE EXPR
  1562.         LXI   H,OVFMSG
  1563.         CALL  ERROR
  1564.         RET
  1565. ;
  1566. UNMSG:  MVI   E,-99         ;  SET VALUE TO -99
  1567.         CALL  ASSIGN
  1568.         CALL  TOP
  1569.         LXI   H,UNFMSG
  1570.         CALL  ERROR
  1571.         RET
  1572. ;
  1573. ; GVALUE - GETS VALUE OF CONSTANT OR VARIABLE
  1574. ;    ENTER:   HL = ADDRESS OF CHAR NAMING THE VARIABLE
  1575. ;             CPTR = ADDRESS OF CHAR
  1576. ;    RETURNS: E = VALUE
  1577. ;             CPTR = ADDRESS OF THE CHARACTER
  1578. ;
  1579. GVALUE: CALL  GETCH         ;GET CHAR
  1580.         MOV   E,A           ;      SAVE IN E
  1581.         CALL  LETTER        ;IF LETTER
  1582.         JZ    LTR           ;  THEN PROCEED
  1583.         CALL  GETNM         ;ELSE EXPECT NUMBER
  1584.         SHLD  CPTR          ;SAVE CHAR POINTER
  1585.         RET
  1586. LTR:    SHLD  CPTR          ;SAVE CHAR POINTER
  1587. CONV:   MOV   B,M           ;   SAVE CHAR IN B
  1588.         CALL  VARMCH        ;LOOK IT UP
  1589.         CPI   1             ;IF END MARKER
  1590.         CZ    BADFRM        ;  THEN COMPLAIN
  1591.         RZ                  ;  AND RETURN
  1592.         INX   H             ;ELSE POINT AT VALUE
  1593.         MOV   E,M           ;   SAVE VALUE IN E
  1594.         RET
  1595. ;
  1596. ; ASSIGN SETS A NEW VALUE TO AN OLD OR NEW VARIABLE
  1597. ;    ENTER:   HLSAV = ADDR OF EXPRESSION FIELD
  1598. ;             BINARY VALUE IN E
  1599. ;
  1600. ASSIGN: LHLD  HLSAV         ;ADDR EXPRESSION FIELD
  1601.         CALL  GETCH         ;GET FIRST CHAR
  1602.         CALL  LETTER        ;IF NOT A LETTER
  1603.         JNZ   EXMSG         ;  THEN COMPLAIN
  1604.         MOV   B,M           ;   GET CHAR IN B
  1605.         CALL  VARMCH        ;LOOK IT UP
  1606.         CPI   1             ;IF END MARKER
  1607.         CZ    BADFRM        ;  THEN COMPLAIN
  1608.         RZ                  ;  AND RETURN
  1609.         INX   H             ;  ELSE BUMP TO VALUE ADDR
  1610.         MOV   M,E
  1611.         RET                 ;  AND RETURN
  1612. ;
  1613. ; BASIC INTERPRETATION -
  1614. ;   IF PROGRAM TEXT IS NOT LEGAL PILOT, THEN
  1615. ;   AN ALTERNATE INTERPRETER SUCH AS BASIC CAN BE
  1616. ;   SUPPLIED TO BE TRIED BEFORE PILOT COMPLAINS.
  1617. ;
  1618. BASIC:  ORA   H             ;DUMMY ILLEGAL RETURN
  1619.         RET
  1620. ;
  1621. ; R OPERATION -
  1622. ;    ENTER:   HLSAV = R-STATEMENT ADDRESS
  1623. ;
  1624. ROP:    RET
  1625. ;
  1626. ; E OPERATION - RETURNS FROM CALL OR ENDS PROGRAM
  1627. ;
  1628. EOP:    LDA   LEVEL         ;IF RETURN LEVEL = 0
  1629.         ORA   A             ;   THEN QUIT
  1630.         JZ    RSTRT
  1631.         CALL  RESRET        ;  ELSE SET RETURN FROM
  1632.         RET                 ;  PILOT CALL
  1633. ;
  1634. LOAD:   LXI   H,PBUFF
  1635.         CALL  INPUT
  1636.         RET
  1637. ;
  1638. ; NEW$ DELETES $NAMES BY RESETTING A-POINTER
  1639. ;
  1640. NEWN:   LHLD  APTR          ;REMOVE STOP CHAR
  1641.         MVI   M,20H
  1642.         LHLD  MEMTP         ;ADDR MEMTP
  1643.         MVI   M,1           ;PLACE STOP CHAR
  1644.         DCX   H
  1645.         SHLD  APTR          ;STORE MEMTP-1 ADDRESS
  1646.         RET
  1647. ;
  1648. ; INITIALIZE NUMERIC VARIABLES
  1649. ;   SETS A-Z TO ZERO VALUE
  1650. ;
  1651. INITV:  LXI   H,NVAR        ;ADDR FRONT OF VAR LIST
  1652.         MVI   B,'A'         ;START WITH 'A'
  1653.         MOV   A,B
  1654. NV:     CPI   'Z'+1         ;IF ALPHABET COMPLETE
  1655.         RZ                  ;THEN RETURN
  1656.         MOV   M,A           ;   STORE THE LETTER
  1657.         INX   H             ;BUMP ADDRESS
  1658.         MVI   A,0
  1659.         MOV   M,A           ;   STORE ZERO
  1660.         INX   H             ;BUMP THE ADDRESS
  1661.         MOV   A,B           ;      GET LETTER
  1662.         ADI   1             ;CHANGE TO NEXT LETTER
  1663.         MOV   B,A           ;   SAVE IN B
  1664.         JMP   NV            ;NEXT VARIABLE
  1665. ;
  1666. ; SAVE RETURN POINTER IN STACK
  1667. ;    ENTER:   IPTR = START OF NEXT SOURCE LINE
  1668. ;    RETURNS: LEVEL BUMPED ONE HIGHER
  1669. ;             IPTR COPIED AT LEVEL POSITION
  1670. ;
  1671. SAVRET: LXI   H,LEVEL       ;GET CURRENT LEVEL
  1672.         MOV   A,M
  1673.         ADI   1             ;BUMP TO NEXT LEVEL
  1674.         CPI   8             ;IF < 8
  1675.         JM    SAV2          ;  THEN CONTINUE
  1676.         LXI   H,STMSG       ;ELSE STACK OVERFLOW
  1677.         CALL  ERROR
  1678.         RET
  1679. SAV2:   MOV   M,A           ;   STORE IT
  1680.         ADD   A             ;DOUBLE IT
  1681.         MOV   C,A           ;      SAVE IN C
  1682.         LHLD  IPTR          ;PUT IPTR IN DE
  1683.         XCHG
  1684.         LXI   H,RETSAV      ;  GET BASE ADDR
  1685.         MOV   A,L
  1686.         ADD   C             ;BASE + 2 X LEVEL
  1687.         MOV   L,A           ;      HL = STACK ADDR
  1688.         MOV   M,D           ;   SAVE IPTR
  1689.         ADI   1
  1690.         MOV   L,A           ;      HL = STACK ADDR+1
  1691.         MOV   M,E
  1692.         RET
  1693. ;
  1694. ; RESET RETURN POINTER FROM STACK
  1695. ;    RETURNS: IPTR SET TO LAST SAVED RETURN
  1696. ;             LEVEL REDUCED BY ONE
  1697. ;
  1698. RESRET: LDA   LEVEL         ;GET RETURN LEVEL
  1699.         ADD   A             ;DOUBLE IT
  1700.         MOV   C,A           ;      SAVE IN C
  1701.         LXI   H,RETSAV      ;  GET BASE ADDR
  1702.         MOV   A,L
  1703.         ADD   C             ;BASE + 2 X LEVEL
  1704.         MOV   L,A           ;      HL = STACK ADDR
  1705.         MOV   D,M           ;   SAVE POINTER IN DE
  1706.         ADI   1
  1707.         MOV   L,A           ;      HL = STACK ADDR+1
  1708.         MOV   E,M
  1709.         XCHG
  1710.         SHLD  IPTR          ;RESET IPTR
  1711.         LXI   H,LEVEL       ;REDUCE LEVEL
  1712.         MOV   A,M
  1713.         SUI   1
  1714.         MOV   M,A
  1715.         RET
  1716. ;
  1717. ; BLOCK TRANSFER FROM HL TO DE, C CHARACTERS
  1718. ;   RETURNS: HL AND DE AT LAST CHAR+1 ADDR
  1719. ;
  1720. BLKTFR: MOV   A,C           ;   GET COUNT
  1721.         ORA   A             ; IF COUNT = 0
  1722.         RZ                  ;  THEN RETURN
  1723.         MOV   B,M           ;   GET A SOURCE CHARACTER
  1724.         INX   H             ;GET NEXT DEST ADDR
  1725.         XCHG
  1726.         MOV   M,B           ;   PUT IT IN DEST LOCATION
  1727.         INX   H             ;GET NEXT SOURCE ADDR
  1728.         XCHG
  1729.         MOV   A,C           ;   DECREMENT COUNT
  1730.         SUI   1
  1731.         MOV   C,A
  1732.         JNZ   BLKTFR        ;IF NONZERO THEN NEXT
  1733.         RET
  1734. ;
  1735. ; KEYBOARD INPUT TO EBUFF
  1736. ;   ENTER:  CHMAX= MAXIMUM CHARS ALLOWED IN LINE
  1737. ;   DEL (SHIFT O) OR RUBOUT CANCELS LAST CHAR
  1738. ;   CTL/U CANCELS CURRENT LINE
  1739. ;   USES B FOR CHAR COUNT, C FOR OUTPUT
  1740. ;
  1741. KEYIN:  LXI   H,EBUFF       ;POINT AT EBUFF
  1742.         SHLD  EPTR          ;SAVE POINTER
  1743.         LXI   H,CHMAX       ;GET MAX COUNT
  1744.         MOV   B,M
  1745. KIN2:   LHLD  EPTR          ;RETRIEVE POINTER
  1746.         CALL  CI            ;GET CHAR AND ECHO
  1747.         CPI   5FH           ;IF DEL
  1748.         JZ    CANC          ;  THEN CANCEL LAST CHAR
  1749.         CPI   7FH           ;IF RUBOUT
  1750.         JZ    CANC          ;  THEN CANCEL LAST CHAR
  1751.         CPI   15H           ;IF CTL/U
  1752.         JZ    CANL          ;  THEN CANCEL LINE
  1753.         CPI   61H           ;FORCE UPPER CASE
  1754.         JM    NTR
  1755.         XRI   20H
  1756. NTR:    MOV   M,A           ;STORE THE CHAR
  1757.         INX   H             ;INCR POINTER
  1758.         SHLD  EPTR          ;SAVE IT
  1759.         CPI   0DH           ;IF CR
  1760.         JZ    KOUT          ;  THEN STOP ENTRY
  1761.         DCR   B             ;ELSE DECR CHAR COUNT
  1762.         MOV   A,B
  1763.         ORA   A             ;IF COUNT NOT 0
  1764.         JNZ   KIN2          ;  THEN NEXT CHAR
  1765.         MVI   C,0DH         ;ELSE END WITH CR
  1766.         MOV   M,C
  1767.         CALL  CO            ;  AND SEND IT
  1768. KOUT:   CALL  LF            ;SEND LINE FEED
  1769.         RET                 ;  AND RETURN
  1770. CANL:   MVI   C,3CH         ;SEND <
  1771.         CALL  CO 
  1772.         CALL  CRLF          ;SEND CRLF
  1773.         JMP   KEYIN         ;  START OVER
  1774. CANC:   MOV   A,B           ;INCR CHAR COUNT
  1775.         LXI   H,CHMAX       ;  UNLESS AT BEGINNING
  1776.         MOV   C,M
  1777.         CMP   C
  1778.         JZ    KIN2
  1779.         INR   B
  1780.         LHLD  EPTR
  1781.         DCX   H             ;DECR POINTER
  1782.         SHLD  EPTR
  1783.         JMP   KIN2+3
  1784. ;
  1785. CRLF:   MVI   C,0DH
  1786.         CALL  CO 
  1787. LF:     MVI   C,0AH
  1788.         CALL  CO 
  1789.         RET
  1790. ;
  1791. ; INPUT PROGRAM TO BUFFER AREA
  1792. ;   DEL (SHIFT O) CANCELS LAST CHAR, CTL/U CANCELS LINE
  1793. ;   TERMINATES WITH CTL/Z (1AH)
  1794. ;
  1795. INPUT:  CALL  BLKBF         ;BLANK THE BUFFER
  1796.         LXI   H,PBUFF       ;SET POINTER
  1797. INPT1:  MOV   A,M           ;GET EXISTING CHAR
  1798.         SHLD  LLSAV         ;SAVE FIRST CHAR ADDR
  1799.         CPI   1             ;IF END MARK
  1800.         JZ    CHOP          ;  THEN CHOP ENTRY
  1801.         CALL  RI            ;GET CHAR
  1802.         CPI   ' '           ;IF NOT BLANK
  1803.         JNZ   INPT3+3       ;  THEN CONTINUE
  1804.         JMP   INPT1         ;ELSE SKIP LEADING BLANK
  1805. INPT2:  MOV   A,M           ;GET EXISTING CHAR
  1806.         CPI   1             ;IF END MARK
  1807.         JZ    CHOP          ;  THEN CHOP ENTRY
  1808. INPT3:  CALL  RI            ;GET CHARACTER
  1809.         CPI   0             ;IGNORE NULLS
  1810.         JZ    INPT3
  1811.         CPI   7FH           ;IGNORE RUBOUTS
  1812.         JZ    INPT3
  1813.         CPI   1AH           ;IF TERM CHAR CTL/Z
  1814.         JZ    INEND         ;  THEN END OF INPUT
  1815.         CPI   15H           ;IF CTL/U
  1816.         JZ    KLN           ;  THEN KILL THE LINE
  1817.         CPI   5FH           ;IF DEL
  1818.         JZ    CLC           ;  THEN CANCEL LAST CHAR
  1819.         MOV   M,A           ;ELSE STORE THE CHAR
  1820.         INX   H             ;AND INCR THE POINTER
  1821.         CPI   0DH           ;IF NOT CR
  1822.         JNZ   INPT2         ;  THEN GET NEXT CHAR
  1823.         CALL  LF            ;ELSE SEND LF
  1824.         JMP   INPT1         ;AND GET NEXT NEW LINE
  1825. INPT4:  MOV   M,A           ;STORE CHAR
  1826.         INX   H             ;INCR POINTER
  1827.         JMP   INPT2
  1828. CLC:    DCX   H             ;CANCEL LAST CHAR
  1829.         JMP   INPT3
  1830. KLN:    MVI   C,3CH         ;SEND <
  1831.         CALL  CO 
  1832.         CALL  CRLF          ;SEND CRLF
  1833.         LHLD  LLSAV         ;ADDR FRONT OF LINE
  1834.         JMP   INPT3
  1835. CHOP:   LHLD  LLSAV         ;ADDR FRONT OF LINE
  1836.         CALL  DSPLY
  1837.         LXI   H,IOVMSG
  1838.         CALL  ERROR
  1839. INEND:  MVI   M,1           ;STORE END MARK
  1840.         SHLD  TOPP          ;STORE ADDRESS
  1841.         CALL  CRLF          ;SEND CRLF
  1842.         LXI   H,LEVEL       ;ZERO RETURN LEVEL
  1843.         MVI   M,0
  1844.         RET
  1845. ;
  1846. ; DISPLAY A CHARACTER STRING TO CR OR 01
  1847. ;   ENTER:  HL = STARTING ADDRESS
  1848. ;   OUTADR CONTAINS ADDRESS OF CO, LO, OR PO
  1849. ;
  1850. DSPLY:  MOV   A,M           ;GET A CHARACTER
  1851.         INX   H             ;BUMP POINTER
  1852.         MOV   D,H           ;SAVE IT
  1853.         MOV   E,L
  1854.         CPI   1             ;IF 01
  1855.         RZ                  ;  THEN RETURN
  1856.         MOV   C,A           ;PUT CHAR IN C
  1857.         LHLD  OUTADR        ;MAKE AN INDIRECT CALL
  1858.         CALL  OVCTR         ;  TO SEND THE CHAR
  1859.         CPI   0DH           ;IF CR
  1860.         JZ    ENDOL         ;  THEN EOL
  1861.         XCHG                ;ELSE RETRIEVE POINTER
  1862.         JMP   DSPLY         ;AND DISPLAY MORE
  1863. ENDOL:  MVI   C,0AH         ;SEND LINE FEED
  1864.         LHLD  OUTADR        ;MAKE AN INDIRECT CALL
  1865.         CALL  OVCTR         ;  TO SEND IT
  1866.         XCHG                ;RETRIEVE POINTER
  1867.         CALL  SKLN           ;SKIP ANY LINE NOS.
  1868.         RET
  1869. OVCTR:  PCHL
  1870. ;
  1871. ; OUTPUT PROGRAM IN MEMORY TO 01 END MARK
  1872. ;
  1873. PRGOUT: LXI   H,PBUFF        ;PGM START ADDR
  1874.         CALL  DSPLY          ;DISPLAY ONE LINE
  1875.         CPI   1              ;IF NOT END MARK
  1876.         JNZ   PRGOUT+3       ;  THEN MORE
  1877.         RET
  1878. ;
  1879. DPRG:   LXI   H,CO           ;DISPLAY PROGRAM IN MEMORY
  1880.         SHLD  OUTADR
  1881.         CALL  PRGOUT
  1882.         RET
  1883. ;
  1884. LPRG:   LXI   H,LO           ;LIST PROGRAM IN MEMORY
  1885.         SHLD  OUTADR
  1886.         CALL  PRGOUT
  1887.         LXI   H,CO           ;RESET TO CONSOLE
  1888.         SHLD  OUTADR
  1889.         RET
  1890. ;
  1891. SPRG:   LXI   H,PO           ;SAVE PROGRAM
  1892.         SHLD  OUTADR
  1893.         CALL  PRGOUT
  1894.         LXI   H,CO           ;RESET TO CONSOLE
  1895.         SHLD  OUTADR
  1896.         RET
  1897. ;
  1898. ; I/O ROUTINES
  1899. ;     USE STPORT (MDS-0F7H) FOR STATUS, PORT (MDS-0F6H) FOR DATA
  1900. ;     STATUS BIT 1 (2H) FOR READ DATA AVAIL (RDA)
  1901. ;     BIT 0 (1H) FOR TRANSMIT BUFFER EMPTY (TBE)
  1902. ;
  1903. ; OUTPUT CHAR FROM C
  1904. ;   LOOKS FOR CTL/Z         INPUT FOR PANIC EXIT
  1905. ;
  1906. CHO:    IN    STPORT    ;GET STATUS
  1907.     ANI    RDA    ;IF NO INPUT
  1908.     JZ    CHO1    ;THEN CONTINUE
  1909.     CALL    CI    ;ELSE SEE WHAT IT IS
  1910.     CPI    1AH    ;IF CNTRL/Z
  1911.     JZ    INTR    ;THEN INTERRUPT
  1912. CHO1:   IN    STPORT          ;NOW FOR STANDARD OUTPUT
  1913.         ANI   TBE
  1914.         JZ    CHO1
  1915.         MOV   A,C
  1916.         OUT   PORT
  1917.         RET
  1918. ;
  1919. INTR:   PUSH  H          ;SAVE REGISTERS
  1920.         PUSH  D
  1921.         PUSH  B
  1922.         LXI   H,INTMSG   ;INTERRUPT MESSAGE
  1923.         CALL  ERROR
  1924.         CALL  ENTRY      ;ALLOW RESTART
  1925.         POP   B          ;ELSE CONTINUE
  1926.         POP   D
  1927.         POP   H
  1928.         RET
  1929. ;
  1930. ; INPUT CHAR TO A AND ECHO
  1931. ;
  1932. CHI:    IN    STPORT          ;NORMAL INPUT
  1933.         ANI   RDA
  1934.         JZ    CHI
  1935.         IN    PORT
  1936.         ANI   7FH
  1937.         MOV   C,A
  1938.         CALL  CO
  1939.         RET
  1940. ;
  1941. ; ERROR - DISPLAYS ERROR MESSAGE
  1942. ;    ENTER:  HL = ADDRESS OF MESSAGE
  1943. ;    RETURNS: ZERO FLAG SET
  1944. ;
  1945. ERROR:  CALL  DSPLY
  1946.         XRA   A
  1947.         RET
  1948. ;
  1949. ; ERROR MESSAGES
  1950. ;
  1951. BLMSG:  DB    '- LABEL NOT FOUND',0DH
  1952. ;
  1953. IOVMSG: DB    '/OVERFLOW',0DH
  1954. ;
  1955. NRMSG:  DB    '*NO ROOM',0DH
  1956. ;
  1957. EXPMSG: DB    '*ILLEGAL EXPRESSION',0DH
  1958. ;
  1959. OVFMSG: DB    '*VALUE >  99',0DH
  1960. ;
  1961. UNFMSG: DB    '*VALUE < -99',0DH
  1962. ;
  1963. STMSG:  DB    '*USE DEPTH EXCEEDED',0DH
  1964. ;
  1965. NMSG:   DB    '*NUMERIC RESPONSE REQUIRED',0DH
  1966. ;
  1967. INTMSG: DB    '*INTERRUPTED',0DH
  1968. ;
  1969. IBUFF:  DB    'T:',0DH
  1970.         DB    'T:PILOT-8080, 1.1',0DH
  1971. ;
  1972.         DB    ':LOAD A NEW PROGRAM?',0DH
  1973. ;
  1974.         DB    'A:',0DH
  1975. ;
  1976.         DB    'M: Y',0DH
  1977. ;
  1978.         DB    'JN:*%',0DH
  1979. ;
  1980.         DB    'T:ENTER PILOT PROGRAM',0DH
  1981. ;
  1982.         DB    ':TERMINATE INPUT WITH CTL/Z',0DH
  1983. ;
  1984.         DB    'LOAD:',0DH
  1985. ;
  1986.         DB    '*% IEP:',0DH
  1987. ;
  1988. ; ORG HERE CAN SET START OF RAM PROGRAM BUFFER SPACE
  1989. ;
  1990.         ORG   PBUFB
  1991. PBUFF:  DB    1
  1992. ;
  1993. ; SOURCE PROGRAM AND $STRING STORAGE HERE TO MEMTP
  1994.         END    START