home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / qterm / qt43src.lbr / CHAT.ZY / CHAT.ZY
Encoding:
Text File  |  1991-05-29  |  23.3 KB  |  993 lines

  1. ; chat.z - handle send/receive chat scripts
  2.  
  3. .incl    "c:vars"
  4.  
  5. .var    _sends    0        ; send string
  6. .var    _expect    40        ; expect string
  7. .var    _explen    80        ; length of expect string
  8. .var    _sndlen    81        ; length of send string
  9. .var    _time    82        ; time in seconds to try
  10. .var    _tries    83        ; number of times to try before failing
  11. .var    _yes    84        ; new state if success
  12. .var    _no    85        ; new state if failure
  13. .var    _slow    86        ; should we slow down outgoing string
  14. .var    _curtry    87        ; current try at this one
  15.  
  16. .useg
  17. .extern    area
  18. area:                ; area where parsed line lives
  19. sends:    ds    40        ; send string
  20. expect:    ds    40        ; expect string
  21. explen:    ds    1        ; length of expect string
  22. sndlen:    ds    1        ; length of send string
  23. time:    ds    1        ; time in seconds to try
  24. tries:    ds    1        ; number of times to try before failing
  25. yes:    ds    1        ; new state if success
  26. no:    ds    1        ; new state if failure
  27. .extern    slow            ; externed for hangup
  28. slow:    ds    1        ; should we slow down outgoing string
  29. curtry:    ds    1        ; current try at this one
  30.  
  31. .cseg
  32.  
  33. .macro    table    byte,addr
  34.     dw    addr
  35.     db    byte
  36. .endm
  37.  
  38. pchat:
  39.     pop    hl        ; needed for chaining
  40.     pop    hl
  41.     jr    ncchat        ; don't clear vars when we chain
  42.  
  43. .extern    chat
  44. chat:
  45.     call    initch        ; set up
  46. ncchat:    ld    a,1
  47.     ld    (opentr),a    ; clear number of open tries
  48.     ld    hl,scning
  49.     dec    (hl)
  50.     call    gofil        ; get and open a file
  51.     ld    hl,scning
  52.     inc    (hl)
  53.     jr    nc,dochat    ; open OK, go do it
  54.     ld    hl,cmdlin
  55.     call    byp        ; look at first char on command line
  56.     or    a        ; no line - give up right now
  57.     ret    z
  58. retryo:    ld    hl,(chtusr)
  59.     inc    h        ; turn to a fcb type drive
  60.     ld    (auxfcb),hl    ; replace drive / user in fcb
  61.     jr    tryaux        ; try it again
  62.  
  63. .extern    ichat            ; enter here with command tail at 80: this
  64. ichat:                ; is used to handle files given to qterm when
  65.                 ; initially invoked
  66.     call    initch
  67.     ld    hl,buffer + 1
  68.     call    scnfcb        ; go parse an fcb
  69.     call    byp
  70.     ld    (ppp),hl    ; save base of parameter strings
  71.     call    xferax        ; stuff it in auxfcb
  72. tryaux:    ld    a,(opentr)
  73.     neg
  74.     ld    (scning),a
  75.     call    opnaux        ; and open it
  76.     ld    hl,scning
  77.     ld    (hl),0        ; reset scanning flag
  78.     inc    hl        ; how many tries
  79.     dec    (hl)        ; second time - must be the .LBR failing
  80.     jr    nc,dochat    ; opened OK, go use it
  81.     ret    nz        ; give up if open failed
  82.     inc    hl
  83.     call    scnfcb
  84.     ld    hl,fcb
  85.     ld    de,auxfcb    ; set pointers to fcbs
  86.     ld    b,34        ; 34 bytes to shift
  87. swplp:    ld    a,(de)
  88.     ld    c,a
  89.     ld    a,(hl)
  90.     ld    (de),a
  91.     ld    (hl),c        ; swap bytes at hl and de
  92.     inc    hl
  93.     inc    de        ; move pointers
  94.     djnz    swplp        ; loop till done
  95.     jr    retryo        ; and retry the open
  96. dochat:    call    nz,setlbr    ; if .LBR file open, then set to read it
  97.     jp    c,fnferr    ; file not found - complain & exit
  98.     ld    hl,(ppp)
  99.     ld    de,0x80        ; move the parameters to 0x80
  100.     ld    b,d
  101.     ld    c,e        ; also 0x80 bytes to move
  102.     ldir            ; shift them down
  103.     call    prepclv        ; prepare the command line variables
  104.     ld    hl,script
  105.     ld    (ppp),hl    ; save address where lines will go
  106.     ld    de,script + 1
  107.     ld    bc,4096 + 1536 - 1
  108.     xor    a
  109.     ld    (hl),a
  110.     ldir            ; clear out the script and work areas
  111.     ld    a,0x7f
  112.     ld    (b7flag),a    ; flag to zap bit 7
  113. loop:    push    bc        ; save line number in bc
  114.     call    getlin        ; get a line
  115.     pop    bc
  116.     jr    c,cnvrt        ; eof - now convert labels and parameters
  117.     ld    hl,auxlin
  118.     ld    a,(hl)
  119.     or    a
  120.     jr    z,loop        ; ditch blank lines
  121.     inc    hl
  122.     cp    '!'        ; first char a '!'
  123.     jr    nz,nobang    ; no - so process normally
  124.     ld    e,(hl)
  125.     call    incbyp
  126.     ld    a,e
  127.     cp    ';'        ; comment??
  128.     jr    z,loop        ; yes - throw it away _RIGHT_NOW_
  129.     cp    ':'        ; label??
  130.     push    af
  131.     call    z,label        ; yes - save it away
  132.     pop    af
  133.     ld    hl,auxlin + 1
  134.     cp    '$'        ; parameter default?
  135.     jr    nz,nodolr
  136.     ld    a,0x81        ; illegal value - not normally seen
  137.     ld    (hl),a        ; set so we don't change
  138. nodolr:    cp    '@'
  139.     jr    nz,nobang
  140.     ld    a,0x82        ; ditto
  141.     ld    (hl),a
  142. nobang:    ld    de,auxlin    ; where the line is
  143.     ld    hl,(ppp)    ; where we want it to go
  144. xferlp:    ld    a,(de)
  145.     ld    (hl),a        ; move a byte
  146.     inc    hl
  147.     inc    de        ; bong the pointers
  148.     or    a
  149.     jr    nz,xferlp    ; loop till whole line is moved
  150.     ld    (ppp),hl
  151.     inc    c
  152.     ld    de,work - 4
  153.     sbc    hl,de        ; did we overflow?
  154.     jr    c,loop        ; no - back for more
  155. toobig:    call    ilprt
  156.     db    'Script is too large (4K maximum)\r\n\0'
  157.     ret
  158.  
  159. ; come here when script has been read, labels noted and parameters set
  160.  
  161. cnvrt:    xor    a
  162.     ld    hl,(ppp)
  163.     ld    (hl),a        ; add an empty line to terminate
  164.     dec    a
  165.     ld    (lbrcnt),a    ; disable library count
  166.     jr    doscr
  167.  
  168. perr:    call    ilprt        ; print an error msg
  169.     db    'Bad line in file\r\n\0'
  170.     call    dim        ; set dim mode
  171.     ld    hl,auxlin    ; point hl at string
  172. erplp:    ld    a,(hl)        ; get a character
  173.     or    a
  174.     jr    z,doneer    ; exit if done
  175.     push    hl
  176.     ld    c,a
  177.     call    scrout        ; send it
  178.     pop    hl
  179.     inc    hl
  180.     jr    erplp
  181. doneer:    call    crlf        ; print a newline
  182.     jp    main        ; and exit to terminal mode
  183.  
  184. doscr:    ld    a,0xff
  185.     ld    (b7flag),a    ; clear bit 7 zap flag
  186.     ld    (cvtp),a
  187.     ld    a,1        ; initially state 1
  188. scrlp:    or    a
  189.     jr    nz,moresc
  190.     push    bc
  191. finisp:    pop    bc
  192. finis:    call    ilprt        ; state zero means we're done
  193.     db    '\r\nDone\r\n\0'
  194.     jp    main        ; straight to main to avoid a second redraw
  195. moresc:    ld    c,a        ; save state in c for command recovery
  196.     dec    a
  197.     ld    b,a
  198.     ld    hl,script    ; point at script
  199.     jr    z,rps        ; if line 1, we're all set
  200. srlp:    ld    a,(hl)
  201.     inc    hl
  202.     or    a
  203.     jr    nz,srlp        ; loop till we hit a null
  204.     djnz    srlp
  205. rps:    ld    (redptr),hl    ; set up read pointer
  206.     push    bc        ; save line number in c
  207.     call    getwl
  208.     jr    c,finisp    ; all out of script, exit
  209.     call    parse        ; chop it up
  210.     jr    c,perr        ; drop on an error
  211.     pop    bc        ; line number back to c
  212.     xor    a
  213.     ld    (curtry),a    ; zero out current try
  214. retry:    ld    ix,area
  215.     ld    a,(sndlen)
  216.     ld    b,a
  217.     or    (ix + _explen)    ; if both strings are empty
  218.     jr    z,finis        ; we fell off end of script: return
  219.     jp    m,commnd    ; explen == -1 => command type line: go do it
  220.     push    ix
  221.     pop    hl        ; address to hl == address of send string
  222.     ld    a,b
  223.     or    a        ; zero length?
  224.     call    nz,sendcs
  225.     ld    a,(ix + _explen) ; get expect length
  226.     or    a
  227.     jr    z,expok        ; not expecting anything, match by default.
  228.     call    clerw2        ; clear the work buffer for incoming chars
  229.     ld    a,(mode)
  230.     and    lf_bit
  231.     jr    nz,scanex
  232.     push    ix
  233.     call    pexstr
  234.     db    '\r\nLooking for: \0'
  235.     pop    ix
  236. scanex:    ld    c,(ix + _time)    ; get time to c
  237. second:    ld    de,600
  238.     call    setspd        ; set the speed
  239. qrtrms:    ld    b,96        ; hang loose a while
  240. qmslp:    djnz    qmslp
  241.     push    hl
  242.     push    bc
  243.     call    procch        ; ok, see what characters are waiting
  244.     jr    c,nochar    ; nothing waiting - bypass all this mess
  245.     call    stufw2        ; and save in the other buffer
  246.     ld    hl,work2 + 257 + 64 + 1
  247.     ld    c,(ix + _explen)
  248.     or    a
  249.     sbc    hl,bc        ; get that point in buffer
  250.     ld    de,expect    ; expect string address to de
  251. chekxp:    ld    a,(de)
  252.     cp    (hl)        ; did we match a byte?
  253.     jr    nz,nochar    ; no - skip and try again
  254.     ldi            ; move pointers, adjust and test bc
  255.     jp    pe,chekxp    ; not done: check some more
  256. gotit:    pop    bc        ; got a match!
  257.     pop    de        ; clean up stack first
  258. expok:    ld    a,(yes)        ; get success state transition
  259.     push    af
  260.     ld    a,(explen)    ; see if we actually had anything to match
  261.     or    a
  262.     jr    z,pjs        ; nope, so skip all of this
  263.     ld    a,(mode)
  264.     and    mat_bit
  265.     jr    nz,pjs        ; don't print if match disabled
  266.     call    pexstr
  267.     db    '\r\nMatch: \0'    ; tell that we matched
  268. pjs:    pop    af        ; restore success state
  269.     jp    scrlp
  270. nochar:    pop    bc
  271.     pop    hl
  272.     dec    hl        ; count down second timer
  273.     ld    a,h
  274.     or    l
  275.     jp    nz,qrtrms
  276.     dec    c        ; second timeout done?
  277.     jp    nz,second    ; loop back if not
  278.     ld    a,(mode)
  279.     and    mat_bit
  280.     jr    nz,nopf        ; don't print if match disabled
  281.     push    ix
  282.     call    ilprt
  283.     db    '\r\nFail\0'    ; failed
  284.     pop    ix
  285. nopf:    inc    (ix + _curtry)    ; bump try count
  286.     ld    a,(curtry)
  287.     cp    (ix + _tries)    ; did we exceed allowed tries?
  288.     jr    nc,failed    ; yes - complete fail - do state transition
  289.     ld    a,(mode)
  290.     and    mat_bit
  291.     jr    nz,jrt        ; don't print if match disabled
  292.     push    ix
  293.     call    ilprt
  294.     db    ', retry\r\n\0'
  295.     pop    ix
  296. jrt:    jp    retry
  297. failed:    ld    a,(no)        ; get fail state transition
  298.     push    af
  299.     call    crlf        ; throw a new line
  300.     jr    pjs
  301.  
  302. .extern    canscr
  303. canscr:    call    ilprt        ; quit if so
  304.     db    '\r\nCancelled\r\n\0'
  305.     jp    main        ; long jump to main since we don't know what
  306.                 ; state the stack is in
  307.  
  308. commnd:    ld    a,c        ; restore line number from c
  309.     ld    (prmpfl),a    ; use non-zero value to set prompt flag
  310.     push    af        ; save line number
  311.     ld    hl,cmdret
  312.     push    hl        ; push a return address to get back here
  313.     ld    a,(time)    ; get the command letter
  314.     call    ucsa        ; force upper case
  315.     ld    hl,chttbl
  316. .dseg
  317. chttbl:    table    '.',break
  318.     table    0x2c,hangup    ; we'd like to say ',',hangup but ZSM barfs
  319.     table    0x82,eval    ; was @, but converted during readin to avoid
  320.                 ; getwl substitute problems
  321.     table    0x81,setstr    ; was $, changed for the same reason.
  322.     table    '#',test
  323.     table    '%',stest
  324.     table    '&',mattog
  325.     table    '<',sinput
  326.     table    '>',messag
  327.     table    '~',cf
  328.     table    '[',multi
  329.     table    '(',fileio
  330.     table    'B',baud
  331.     table    'C',catch
  332.     table    'E',echo
  333.     table    'H',hdxtog
  334.     table    'J',jctog
  335.     table    'K',ldfnk
  336.     table    'L',lftog
  337.     table    'M',msbtog
  338.     table    'N',newdsk
  339.     table    'O',optog
  340.     table    'P',print
  341.     table    'Q',quit
  342.     table    'R',recv
  343.     table    'S',send
  344.     table    'U',0x0276
  345.     table    'V',vttog
  346.     table    'W',witog
  347.     table    'X',pchat
  348.     table    'Y',hold
  349.     table    'Z',cclose
  350. endctb:
  351. .cseg
  352.     ld    b,{endctb - chttbl} / 3
  353. tbllp:    ld    e,(hl)
  354.     inc    hl
  355.     ld    d,(hl)        ; get next table entry to de
  356.     inc    hl
  357.     cp    (hl)        ; check byte in a vs. table letter
  358.     inc    hl
  359.     push    de        ; push entry point
  360.     ret    z        ; if we matched this takes us to the code
  361.     pop    de        ; restore stack
  362.     djnz    tbllp        ; loop till we run out of table
  363.     pop    hl        ; clean up stack
  364. cmdret:    xor    a
  365.     ld    (prmpfl),a    ; clear prompt flag
  366.     pop    af        ; get line number back
  367.     inc    a        ; bump by one: commands always succeed
  368.     jp    scrlp        ; loop back for more
  369.  
  370. .extern    sendcs
  371. sendcs:
  372.     inc    b        ; clear the zero flag, and account for an
  373.                 ; extra djnz
  374.     push    bc
  375.     push    hl        ; stack these for later popping
  376.     jr    sendi        ; and jump to where we delay a bit
  377.  
  378. sendcl:    push    bc
  379.     ld    a,(hl)        ; get next character
  380.     inc    hl        ; bump
  381.     push    hl        ; and save pointer
  382.     cp    0xff        ; was it a -1?
  383.     jr    nz,nosbrk    ; no - check for -2
  384.     call    break        ; send a break
  385.     jr    chrsnt
  386. nosbrk:    cp    0xfe        ; check for -2
  387.     jr    nz,mdmchr    ; no - send char normally
  388.     ld    de,1200        ; set for a 1 second delay
  389.     call    msip        ; 1000 1/1000th of a second == 1 second
  390.     jr    chrsnt        ; and check for incoming chars
  391. mdmchr:    push    af
  392.     call    modop        ; send the character
  393.     pop    af        ; restore back to a
  394. chrsnt:    call    lstmod        ; keep tabs on incoming chars
  395.     call    lstmod
  396.     ld    a,(slow)
  397.     or    a        ; do we need to slow it down
  398. sendi:    call    nz,tenth    ; wait a while if so
  399.     pop    hl
  400.     pop    bc
  401.     djnz    sendcl        ; and keep on sending
  402.     ret
  403.  
  404. parse:    ld    hl,area        ; point de at this record
  405.     push    hl
  406.     ld    de,area + 1
  407.     ld    bc,_curtry
  408.     ld    (hl),b
  409.     ldir            ; nuke parse area
  410.     pop    de        ; restore input pointer to de
  411.     ld    hl,auxlin
  412.     ld    a,(hl)
  413.     cp    '!'        ; bang?
  414.     jr    nz,nopb        ; nope - parse as usual
  415.     inc    hl
  416.     ld    a,(hl)        ; get command letter
  417.     inc    hl
  418.     ld    bc,_explen    ; move enough stuff to fill to explen
  419.     ldir
  420.     ex    de,hl
  421.     ld    (hl),b        ; null terminate just in case
  422.     inc    hl
  423.     ld    (hl),-1        ; set -1 in sndlen as a flag
  424.     inc    hl
  425.     ld    (hl),a        ; and save the letter
  426.     ret
  427. nopb:    ld    hl,slow
  428.     ld    (hl),b
  429.     ld    a,(auxlin)    ; get delimiter
  430.     cp    'z' + 1        ; greater than 'z'?
  431.     jr    c,noslow    ; skip if not
  432.     ld    (hl),a        ; else set slow flag
  433. noslow:    ld    hl,auxlin    ; point hl at incoming line
  434.     call    scanst        ; scan send string
  435.     ret    c
  436.     ld    (sndlen),a    ; save length
  437.     call    scanst        ; scan expect string
  438.     ld    (explen),a
  439.     ret    c        ; exit if error
  440.     xor    a
  441.     call    rednum        ; parse time
  442.     ret    c
  443.     or    a
  444.     jr    nz,gottim
  445.     ld    a,15        ; if no time or zero, default to 15
  446. gottim:    ld    de,time
  447.     ld    (de),a        ; save the time
  448.     inc    de
  449.     xor    a
  450.     call    rednum        ; scan tries
  451.     ret    c
  452.     or    a
  453.     jr    nz,gottry
  454.     inc    a        ; if none or zero set to 1
  455. gottry:    ld    (de),a
  456.     inc    de
  457.     pop    bc
  458.     ex    (sp),hl
  459.     ld    a,l        ; get cur line num to a
  460.     ex    (sp),hl
  461.     push    bc
  462.     inc    a        ; add one to get default yes
  463.     call    rednum        ; read success
  464.     ret    c
  465.     ld    (de),a
  466.     inc    de
  467.     xor    a
  468.     call    rednum        ; and finally the fail value
  469.     ret    c
  470.     ld    (de),a
  471.     inc    a
  472.     ret
  473.  
  474. .extern    scanst
  475. scanst:    ld    b,40        ; count max of 40 chars
  476.     ld    a,(hl)        ; get the delimiter to a
  477.     ld    (de),a
  478.     or    a
  479.     ret    z        ; return with z to show empty line
  480.     ld    c,a        ; copy to c
  481.     inc    hl        ; point to next char
  482.  
  483. .extern    scnstp
  484. scnstp:    call    parst        ; chomp up the string
  485.     ret    c
  486. donest:    ld    a,40
  487.     sub    b        ; get length to a
  488.     dec    b
  489.     inc    b        ; test b for zero
  490.     jr    z,bzero        ; if b not zero
  491. setde:    inc    de        ; bump de
  492.     djnz    setde        ; till b runs out
  493. bzero:    or    a        ; clear the carry
  494.     ret
  495.  
  496. .extern    parst
  497. parst:
  498.     xor    a
  499.     ld    (de),a        ; add a trailing null
  500.     ld    a,(hl)        ; get next char
  501.     cp    c        ; delimiter?
  502.     ret    z        ; yes - all done on this string
  503.     or    a
  504.     ccf
  505.     ret    z        ; handle error
  506.     inc    hl
  507.     cp    '\\'        ; backslash gets special treatment
  508.     call    z,backsl    ; parse the backslash escape
  509.     inc    b
  510.     dec    b        ; any space left?
  511.     jr    z,parst        ; no - just get end of line
  512.     dec    b
  513.     ld    (de),a        ; save the char away
  514.     inc    de
  515.     jr    parst
  516.  
  517. .extern    backsl
  518. backsl:    ld    a,(hl)        ; get char after backslash
  519.     inc    hl
  520.     or    a        ; end of string?
  521.     scf            ; flip carry to true
  522.     ret    z        ; return on zero w/ error
  523.     cp    'k'
  524.     jr    nz,nobrk
  525.     ld    a,0xff
  526.     ret
  527. nobrk:    cp    'd'
  528.     jr    nz,nodel
  529.     ld    a,0xfe
  530.     ret
  531. nodel:    cp    'f'
  532.     jr    nz,noff
  533.     ld    a,'\f'
  534.     ret
  535. noff:    cp    'b'
  536.     jr    nz,nobksp
  537.     ld    a,'\b'
  538.     ret
  539. nobksp:    cp    't'
  540.     jr    nz,notab
  541.     ld    a,'\t'
  542.     ret
  543. notab:    cp    'n'
  544.     jr    nz,nonl
  545.     ld    a,'\n'
  546.     ret
  547. nonl:    cp    'r'
  548.     jr    nz,nocr
  549.     ld    a,'\r'
  550.     ret
  551. nocr:    cp    'e'
  552.     jr    nz,noesc
  553.     ld    a,'\e'
  554.     ret
  555. noesc:    cp    'x'
  556.     jr    nz,nohex
  557.     push    bc
  558.     ld    bc,0x0200
  559. gethex:    ld    a,(hl)
  560.     sub    '0'
  561.     cp    10
  562.     jr    c,hexok        ; valid digit - use it
  563.     sub    'A' - '0'
  564.     cp    6
  565.     jr    c,hexlok    ; valid A-F
  566.     sub    'a' - 'A'
  567.     cp    6
  568.     jr    c,hexlok    ; valid a-f
  569.     ld    a,b
  570.     add    a,0xfe        ; check if b was still 2
  571.     jr    endoct
  572. hexlok:    add    a,10        ; letter values need 10 added
  573. hexok:    inc    hl        ; bump pointer
  574.     sla    c
  575.     sla    c
  576.     sla    c
  577.     sla    c        ; c *= 16
  578.     or    c        ; a += c
  579.     ld    c,a    
  580.     djnz    gethex
  581.     jr    endoct
  582. nohex:    sub    '0'        ; check for octal digit
  583.     cp    8
  584.     jr    c,octal        ; got one - handle it
  585.     add    a,'0'        ; restore character
  586.     or    a        ; clear carry
  587.     ret
  588. octal:    push    bc
  589.     ld    b,2        ; 2 more chars to get
  590.     ld    c,a        ; save current value in c
  591. getoct:    ld    a,(hl)        ; get another char
  592.     sub    '0'
  593.     cp    8        ; convert and test
  594.     jr    nc,endoct    ; no good - skip
  595.     inc    hl        ; now we move the pointer
  596.     sla    c
  597.     sla    c
  598.     sla    c        ; c *= 8
  599.     or    c        ; a += c (and clear the carry)
  600.     ld    c,a        ; back to c
  601.     djnz    getoct        ; loop till three chars done
  602. endoct:    ld    a,c        ; char back from c
  603.     pop    bc
  604.     ret
  605.  
  606. rednum:    ex    af,af'        ; save default value in a'
  607.     ld    a,(hl)
  608.     or    a        ; get and test a delimiter
  609.     jr    z,usedef    ; end of string - use default
  610.     inc    hl
  611.     ld    c,a        ; save it away
  612.     ld    a,(hl)
  613.     cp    c        ; check see if anything in field
  614.     jr    nz,isnum    ; yes - go parse it
  615. usedef:    ex    af,af'
  616.     ret
  617. isnum:    ld    b,0
  618. scnnum:    ld    a,(hl)
  619.     or    a
  620.     jr    z,usedef    ; end of string: exit
  621.     cp    c
  622.     jr    z,gotnum    ; found delimiter: exit
  623.     inc    hl
  624.     sub    '0'
  625.     cp    10        ; did we find a digit?
  626.     ccf            ; flip carry: set => error
  627.     ret    c        ; so return
  628.     push    af        ; save converted digit
  629.     ld    a,b
  630.     add    a,a
  631.     add    a,a
  632.     add    a,b
  633.     add    a,a
  634.     ld    b,a        ; b *= 10
  635.     pop    af
  636.     add    a,b
  637.     ld    b,a        ; b += new digit
  638.     jr    scnnum
  639. gotnum:    ld    a,b
  640.     ret
  641.  
  642. ; label saves a label / line number pair in the symbol table
  643.  
  644. label:    push    hl        ; save input pointer
  645.     ld    hl,work + 1016    ; look in symbol table
  646.     ld    de,8        ; step 8 at a time
  647. findlb:    add    hl,de        ; move to next
  648.     ld    a,(hl)
  649.     or    a        ; end of table?
  650.     jr    nz,findlb    ; no - look at next one
  651.     pop    de        ; input pointer back to de
  652.     ld    b,7        ; 7 bytes of label
  653. scanit:    ld    a,(de)        ; get an input byte
  654.     or    a
  655.     jr    z,elbl        ; null
  656.     cp    ' '
  657.     jr    z,elbl        ; or space terminates it
  658.     ld    (hl),a
  659.     inc    de
  660.     inc    hl
  661.     djnz    scanit        ; loop till 7 bytes moved
  662.     jr    addnum        ; go add the line number
  663. elbl:    ld    (hl),0
  664.     inc    hl        ; zero fill
  665.     djnz    elbl
  666. addnum:    ld    (hl),c        ; save the line number
  667.     xor    a
  668.     inc    hl
  669.     ld    (hl),a        ; zero fill end of symtab
  670.     ld    (work + 1528),a ; prevent overflow
  671.     ret
  672.  
  673. ; flabel - find a label / line number pair in the symbol table
  674.  
  675. flabel:    ex    de,hl        ; label pointer to de
  676.     ld    hl,work + 1016    ; look in symbol table
  677. flblp:    ld    bc,8        ; step 8 at a time
  678.     add    hl,bc        ; move to next
  679.     ld    a,(hl)
  680.     or    a        ; end of table?
  681.     jr    z,exdert    ; yes - undefined labels do odd things
  682.     ld    a,(de)
  683.     cp    (hl)        ; check first char
  684.     jr    nz,flblp    ; nope - try again
  685.     push    hl
  686.     push    de        ; save pointers
  687.     ld    b,7        ; 7 bytes of label
  688. fscnit:    ld    a,(de)        ; get an input byte
  689.     or    a
  690.     jr    z,nomtch    ; end of input
  691.     cp    (hl)
  692.     jr    nz,nomtch    ; no match, but it may be end of label
  693.     inc    de        ; bump pointers
  694. endok:    inc    hl
  695.     djnz    fscnit        ; all 7 bytes done: we got it
  696.     ld    a,(hl)        ; get line number to a
  697.     pop    hl
  698.     pop    hl        ; clean stack
  699. exdert:    ex    de,hl        ; input pointer back to hl
  700.     ret            ; and home we go
  701. nomtch:    ld    a,(hl)
  702.     or    a
  703.     jr    z,endok        ; aha - end of entry in symtab, fake it
  704.     pop    de
  705.     pop    hl        ; no good, restore pointers
  706.     jr    flblp        ; back to look at the next one
  707.  
  708. ; fparam - find parameter from array at 0x80 whose number is in a
  709.  
  710. .extern    fparam
  711. fparam:    ld    hl,strngs    ; point at strings
  712. fplp:    or    a        ; finished?
  713.     ret    z        ; return if so - hl points to string
  714.     ld    e,a        ; save a
  715. byppl:    ld    a,(hl)        ; step over non-null characters
  716.     inc    hl
  717.     or    a
  718.     jr    nz,byppl
  719.     ld    a,e        ; get string number back
  720.     dec    a        ; one more done
  721.     jr    fplp
  722.  
  723. ; kilstr - kill string parameter hl points to
  724.  
  725. .extern    kilstr
  726. kilstr:    ld    a,(hl)
  727.     or    a
  728.     ret    z        ; if it's already empty, we're done
  729.     push    hl        ; save hl for later
  730.     ld    e,l
  731.     ld    d,h
  732. ksel:    inc    hl        ; loop to find end of old string
  733.     ld    a,(hl)
  734.     or    a
  735.     jr    nz,ksel
  736. shftlp:    ld    a,(hl)        ; by now hl points to end, de to string
  737.     ldi            ; move another byte
  738.     inc    a        ; test for end of data
  739.     jr    nz,shftlp    ; loop till all done
  740.     ex    de,hl
  741. xfill:    ld    (hl),0xff    ; replace all the 0xffs
  742.     inc    hl
  743.     ld    a,(hl)
  744.     cp    'A'        ; we've got an 'A' at the end as a stopper
  745.     jr    nz,xfill
  746.     pop    hl        ; restore pointer to string
  747.     ret            ; all done
  748.  
  749. ; setstr - set a string variable
  750.  
  751. setstr:    call    areabu        ; point hl at command tail
  752.     call    pnum
  753.     ret    nc
  754.     inc    hl        ; skip over letter
  755.     push    hl        ; and save address of source
  756.     push    af        ; save parm number
  757.     call    fparam        ; get ...
  758.     pop    af
  759.     cp    9
  760.     jr    nc,repl        ; 9 or above is letter string - force replace
  761.     ld    a,(hl)
  762.     or    a        ; anything there yet?
  763.     jr    nz,pbcret    ; yes - do nothing
  764. repl:    call    kilstr        ; and kill current string
  765.     ex    (sp),hl        ; save target, restore source
  766.     call    byp        ; strip white space
  767.     ex    de,hl        ; source to de
  768.     pop    hl        ; dest back to hl
  769.     xor    a        ; want this null terminated
  770.                 ; and fall into insstr to put it in place
  771.  
  772. ; insstr - shift string addressed by de to string var at hl, use char in
  773. ; a (or null) to terminate string at de
  774.  
  775. .extern    insstr
  776. insstr:    push    bc        ; save bc
  777.     ld    b,a        ; term char to b
  778.     ld    c,0        ; count in c
  779.     push    de        ; save source in de
  780. fslen:    ld    a,(de)
  781.     or    a        ; null
  782.     jr    z,estr1        ; ends the string
  783.     cp    b        ; term char?
  784.     jr    z,estr        ; yup end of string as well
  785.     inc    c        ; count
  786.     inc    de        ; and move pointer
  787.     jr    fslen
  788. estr:    xor    a
  789. estr1:    ld    b,a        ; set len to word in bc
  790.     cp    c
  791.     jr    z,pop2r
  792.     push    hl        ; save target in hl
  793.     push    bc        ; and length as well
  794.     inc    bc
  795.     ld    hl,strngs + 511    ; start from very top of string space
  796.     cpdr            ; look for 0 on end of last string
  797.     pop    bc
  798.     jr    nz,isok        ; nz means we didn't find it which is OK
  799.     pop    hl        ; get hl back
  800. pop2r:    pop    bc
  801.     pop    bc        ; clean up stack, de points to end already
  802.     ret            ; exit right now
  803. isok:    pop    de        ; target back to de
  804.     inc    hl
  805.     push    hl        ; source of lddr on stack
  806.     sbc    hl,de        ; hl contains count to move up
  807.     push    bc        ; length back on stack
  808.     ld    b,h
  809.     ld    c,l        ; count to move to bc
  810.     pop    hl        ; length back to hl
  811.     ex    (sp),hl        ; resave length, get lower move point
  812.     push    de        ; target back on stack
  813.     ld    de,strngs + 511
  814.     inc    bc        ; why in the name of H*LL we have to inc this
  815.     inc    bc        ; twice, I don't know. However, it works.
  816.     lddr            ; shift it all up to make the hole
  817.     pop    de        ; target back
  818.     pop    bc        ; length of string back
  819.     pop    hl        ; source
  820.     push    de        ; save target
  821.     ldir            ; move string into place
  822.     ex    de,hl        ; updated source pointer back to de
  823.     pop    hl        ; original hl back
  824. pbcret:    pop    bc        ; restore bc
  825.     ret
  826.  
  827. pnum:;    call    ucsa
  828.     sub    '1'
  829.     cp    9        ; is it valid
  830.     ret    c        ; default param
  831.     sub    'A' - '1'
  832.     cp    26        ; valid letter?
  833.     ret    nc        ; return if not
  834.     add    a,9        ; convert above parameters
  835.     scf            ; set carry to show it's OK
  836.     ret
  837.  
  838. ; prepclv - convert command line args to $1 through $9
  839.  
  840. prepclv:
  841.     ld    de,0x80        ; point at command line params
  842.     ld    b,0        ; set counter to zero
  843. pcvlp:    push    de
  844.     ld    a,b
  845.     call    fparam        ; address this parameter
  846.     call    kilstr        ; get rid of the old
  847.     pop    de
  848.     ex    de,hl
  849.     call    byp        ; find text
  850.     ex    de,hl
  851.     ld    a,' '
  852.     call    insstr        ; drop the string in place
  853.     inc    b
  854.     ld    a,b
  855.     cp    9        ; loop till nine are done
  856.     jr    nz,pcvlp
  857.     ret
  858.  
  859. ; get a line from wherever we're reading, stuff it in auxlin
  860.  
  861. getwl:    ld    hl,(redptr)    ; pick up read pointer
  862.     ld    a,(hl)
  863.     or    a        ; first byte zero?
  864.     scf
  865.     ret    z        ; return carry to show end of input
  866.     ld    de,auxlin    ; auxlin is where we'll put it
  867. gwlp:    ld    a,(hl)        ; get a byte
  868.     cp    '$'
  869.     jr    z,gwstr        ; substitute strings,
  870.     cp    '@'
  871.     jr    z,gwnum        ; numbers
  872.     cp    '`'
  873.     jr    z,gwlbl        ; and labels
  874. nullt:    ld    a,(hl)
  875.     ldi            ; otherwise just transfer
  876.     or    a        ; and test the byte
  877.     jr    nz,gwlp        ; loop if more
  878.     ld    (redptr),hl    ; save updated read pointer
  879.     ret
  880.  
  881. gwstr:    inc    hl        ; point at letter code for string wanted
  882.     call    ucsahl
  883.     ; ld    a,(hl)        ; get it
  884.     call    pnum        ; see if it's a valid string number
  885.     jr    nc,nullt    ; if not just copy the character as is
  886.     inc    hl
  887.     push    hl        ; save string we're reading from
  888.     push    de
  889.     call    fparam        ; get the string
  890.     pop    de
  891. scp:    ld    a,(hl)
  892.     or    a
  893.     jr    z,phlgwl
  894.     ldi
  895.     jr    scp
  896. phlgwl:    pop    hl
  897.     jr    gwlp
  898.  
  899. gwnum:    inc    hl        ; point at variable letter
  900.     call    ucsahl        ; convert to upper case
  901.     sub    'A'        ; make it into an index
  902.     cp    26        ; in range?
  903.     jr    nc,nullt    ; nope - convert as a straight letter
  904.     inc    hl        ; skip over the variable number
  905.     push    hl        ; save source
  906.     push    de        ; and target
  907.     ld    e,a
  908.     ld    d,0
  909.     ld    hl,vars
  910.     add    hl,de
  911.     ld    a,(hl)        ; fetch the value
  912.     pop    hl        ; restore target to hl
  913.     jr    dumpa
  914.  
  915. gwlbl:    inc    hl
  916.     push    de        ; save target
  917.     call    flabel        ; find the label
  918.     inc    a
  919.     ex    (sp),hl        ; restore target, save source
  920.  
  921. dumpa:    ld    (hl),'0' - 1    ; put in hundreds digit
  922.     ld    e,0
  923. hundlp:    inc    (hl)
  924.     sub    100
  925.     jr    nc,hundlp
  926.     add    a,100
  927.     call    cinc
  928.     ld    (hl),'0' - 1
  929. tenlp:    inc    (hl)
  930.     sub    10
  931.     jr    nc,tenlp
  932.     call    cinc
  933.     add    a,'0' + 10
  934.     ld    (hl),a
  935.     inc    hl
  936.     ex    de,hl        ; target back to de
  937.     pop    hl        ; source to hl
  938.     jr    gwlp        ; and we're done
  939.  
  940. ; cinc - inc hl only if (hl) != 0: used to format numbers
  941.  
  942. cinc:    dec    e
  943.     inc    e        ; test e
  944.     jr    nz,docinc    ; already set, force a save
  945.     ld    c,a        ; save a
  946.     ld    a,(hl)
  947.     cp    '0'        ; pointing at a zero?
  948.     ld    a,c        ; restore a
  949.     ret    z        ; return if so,
  950. docinc:    inc    hl        ; otherwise bump hl
  951.     inc    e        ; and set e
  952.     ret
  953.  
  954. ; print expect string, but ignore control characters
  955.  
  956. pexstr:    call    dim        ; dim mode
  957.     pop    hl
  958.     call    prtslp        ; print inline string
  959.     push    hl        ; resave return address
  960.     ld    hl,expect
  961.     ld    bc,(explen - 1)    ; get explen to b
  962. prtncc:    ld    a,(hl)        ; get a character
  963.     cp    ' '
  964.     jr    c,nopcc        ; less than space, don't print
  965.     cp    0x7f        ; check >= delete
  966.     push    bc
  967.     push    hl
  968.     ld    c,a        ; char to c for printout
  969.     call    c,scrout    ; out it goes if legal
  970.     pop    hl
  971.     pop    bc
  972. nopcc:    inc    hl        ; move pointer
  973.     djnz    prtncc        ; loop till all done
  974.     jp    crlf
  975.  
  976. .dseg
  977. .extern    scning
  978. scning:    db    0
  979. .extern    opentr
  980. opentr:    db    0        ; should be useg, but need to bump hl for lbrs
  981. .extern    lbrs
  982. lbrs:    db    '/QTERM.LBR\0'    ; name of qterm script library
  983.  
  984. .useg
  985. redptr:    ds    2
  986. .extern    ppp
  987. ppp:    ds    2        ; parameter pointer
  988. .extern    chtusr
  989. chtusr:    ds    1        ; extra drive / user to try for chat scripts
  990. .extern    chtdrv
  991. chtdrv:    ds    1
  992. cvtp:    ds    1        ; do we convert params and numbers in getwl
  993.