home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / archives / ccdos.zip / ccster.asm < prev    next >
Assembly Source File  |  1991-09-08  |  35KB  |  785 lines

  1.         NAME    ccster
  2. ; File CCSTER.ASM
  3.  
  4. ;CHINESE
  5. ifdef   MSDOS
  6.         include msster.dat
  7. else
  8.         include ccster.dat
  9. endif
  10.  
  11. code    segment public 'code'
  12.         extrn   comnd:near, outchr:near, stat0:near, iseof:near
  13.         extrn   clrbuf:near, term:near, strlen:near
  14.         extrn   prtchr:near, ihostr:near
  15.         extrn   beep:near, puthlp:near, getbaud:near, serhng:near
  16.         extrn   serini:near,serrst:near, sendbr:near, showkey:near
  17.         extrn   fpush:near, dumpscr:near, pcwait:near, sendbl:near
  18.         assume  cs:code, ds:datas
  19.  
  20. ; the show key command
  21. shokey  proc    near
  22.         cmp     shkadr,0                ; keyboard translator present?
  23.         je      shokey1                 ; e = no, use regular routines
  24.         mov     bx,shkadr               ; get offset of replacement routine
  25.         jmp     bx                      ; and execute it rather than us
  26. shokey1:jmp     rskp                    ; and return
  27. shokey  endp
  28. ; enter with ax/scan code to define, si/ pointer to definition, cx/ length
  29. ; of definition.  Defines it in definition table. Obsolete.
  30. defkey  proc    near
  31.         ret
  32. defkey  endp
  33.  
  34. ; This is the CONNECT command
  35.  
  36. TELNET  PROC    NEAR
  37.         mov     ah,cmcfm
  38.         call    comnd                   ; Get a confirm
  39.          jmp    r                       ;  Didn't get a confirm
  40.         mov     ah,prstr                ; Output
  41.         mov     dx,offset crlf          ; a crlf
  42.         int     dos
  43.         cmp     flags.vtflg,0           ; emulating a terminal?
  44.         jne     teln1                   ; ne= yes, skip flashing message
  45.         call    domsg                   ; Reassure user
  46. teln1:  call    serini                  ; ensure port is inited now
  47.         mov     al,0                    ; initial flags
  48.         mov     ttyact,1                ; say telnet is active
  49.         cmp     flags.modflg,0          ; mode line enabled?
  50.         jne     tel010                  ; ne = yes
  51.         or      al,modoff               ; no, make sure it stays off
  52.  
  53. tel010: or      al,havtt                ; defaults (!)
  54.         test    flags.debug,logses      ; debug mode?
  55.         jz      tel0                    ; z = no, keep going
  56.         or      al,trnctl               ; yes, show control chars
  57. tel0:   cmp     flags.vtflg,0           ; emulating a terminal?
  58.         je      tel1                    ; e = no
  59.         or      al,emheath              ; say emulating some kind of terminal
  60. tel1:   mov     bx,portval
  61.         cmp     [bx].ecoflg,0           ; echoing?
  62.         jz      tel2
  63.         or      al,lclecho
  64. tel2:   call    getbaud                 ; pickup current baud rate for port
  65.         mov     targ.flgs,al            ; store flags
  66.         mov     ah,flags.comflg         ; COMs port identifier
  67.         mov     targ.prt,ah             ; Port 1 or 2, etc
  68.         mov     ah,trans.escchr         ; escape character
  69.         mov     targ.escc,ah
  70.         mov     ah,[bx].parflg          ; parity flag
  71.         mov     targ.parity,ah
  72.         mov     ax,[bx].baud            ; baud rate identifier
  73.         mov     targ.baudb,al
  74.         xor     ah,ah
  75.         test    flags.capflg,logses     ; select session logging flag bit
  76.         jz      tel3                    ; z = no logging
  77.         mov     ah,capt                 ; set capture flag
  78. tel3:   or      targ.flgs,ah
  79.  
  80. TEM:    call    serini                  ; init serial port
  81.         jnc     tem0                    ; nc = success
  82.         mov     ttyact,0                ; say we are no longer active
  83.         jmp     rskp                    ; and exit Connect mode
  84.  
  85. tem0:   mov     dx,offset crlf          ; give user an indication that we are
  86.         mov     ah,prstr                ; entering terminal mode
  87.         int     dos
  88.         mov     ax,offset targ          ; Point to terminal arguments
  89.         call    term                    ; Call the main Terminal procedure
  90.         or      targ.flgs,scrsam        ; assume screen is the same
  91. tem1:   mov     al,kbdflg               ; get the char from Term, if any
  92.         mov     kbdflg,0                ; clear the flag
  93.         cmp     al,0                    ; was there a char from Term?
  94.         jne     intch2                  ; ne = yes, else ask for one from kbd
  95.  
  96. intchar:call    iseof                   ; stdin at eof?
  97.         jnc     intch1                  ; nc = not eof, get more
  98.         mov     al,'C'                  ; use C when file is empty
  99.         jmp     intchc                  ;  to provide an exit
  100. intch1: mov     ah,coninq               ; read keyboard, no echo
  101.         int     dos                     ; get a char
  102.         cmp     al,0                    ; scan code indicator?
  103.         jne     intch2                  ; ne = no, ascii
  104.         mov     ah,coninq               ; read and discard scan code
  105.         int     dos
  106.         jmp     short intch1            ; try again
  107. intch2: cmp     al,' '                  ; space?
  108.         je      tem                     ; e = yes, ignore it
  109.         cmp     al,cr                   ; check ^M (cr) against plain ascii M
  110.         je      tem                     ; exit on cr
  111.         cmp     al,trans.escchr         ; Is it the escape char?
  112.         jne     intch3                  ; ne = no
  113.         mov     ah,al
  114.         call    outchr
  115.          nop
  116.          nop
  117.          nop
  118.         jmp     tem                     ; Return, we are done here
  119. intch3: push    es
  120.         push    ds
  121.         pop     es
  122.         mov     di,offset intclet       ; command letters
  123.         mov     cx,numlet               ; quantity of them
  124.         cmp     al,' '                  ; control code?
  125.         jae     intch3a                 ; ae = no
  126.         or      al,40H                  ; convert control chars to printable
  127. intch3a:cmp     al,96                   ; lower case?
  128.         jb      intch3b                 ; b = no
  129.         and     al,not (20h)            ; move to upper case
  130. intch3b:cld
  131.         repne   scasb                   ; find the matching letter
  132.         pop     es
  133.         jne     intch4                  ; ne = not found, beep and get another
  134.         dec     di                      ; back up to letter
  135.         sub     di,offset intclet       ; get letter number
  136.         shl     di,1                    ; make it a word index
  137.         jmp     intcjmp[di]             ; dispatch to it
  138. intch4: call    beep                    ; say illegal character
  139.         jmp     intchar
  140.  
  141. intchb: call    sendbr                  ; 'B' send a break
  142.         jmp     tem                     ; And return
  143.  
  144. intchc: mov     ttyact,0                ; 'C' say we are no longer active
  145.         jmp     rskp                    ; and exit Connect mode
  146.  
  147. intchf: call    dumpscr                 ; 'F' dump screen, use msy routine
  148.         jmp     tem                     ; and return
  149.  
  150. intchh: call    serhng                  ; 'H' hangup phone
  151.         call    serrst                  ; turn off port
  152.         jmp     tem
  153.  
  154. intchl: call    sendbl                  ; 'L' send a long break
  155.         jmp     tem
  156.  
  157. intchm: cmp     flags.modflg,1          ; 'M' toggle mode line, enabled?
  158.         jne     intchma                 ; ne = no, leave it alone
  159.         xor     targ.flgs,modoff        ; enabled, toggle its state
  160. intchma:jmp     tem                     ; and reconnect
  161.  
  162. intchp: push    bx                      ; 'P' push to DOS
  163.         mov     bx,portval
  164.         mov     ah,byte ptr [bx].flowc  ; get XOFF char, or null
  165.         pop     bx
  166.         or      ah,ah                   ; check for null (no flow control)
  167.         jz      intchpa                 ; z = null, don't send one
  168.         call    outchr                  ; send XOFF to host while we are away
  169.          nop
  170.          nop
  171.          nop
  172. intchpa:call    serrst                  ; turn off serial interrupts
  173.         call    fpush                   ; try pushing
  174.          nop
  175.          nop
  176.          nop
  177. ;        mov     dx,offset sttmsg        ; say we have returned
  178.         mcmsg   sttmsg,csttmsg
  179.         mov     ah,prstr
  180.         int     dos
  181.         call    serini                  ; init serial port again
  182.         jc      intchc                  ; nc = failure
  183.         call    ihostr                  ; XON the host (if using flow control)
  184.         jmp     intchsb                 ; wait for a space
  185.  
  186. intchq: test    targ.flgs,capt          ; 'Q' suspend logging. Logging active?
  187.         jz      intchq1                 ; z = no
  188.         and     targ.flgs,not capt      ; stop capturing
  189. intchq1:jmp     tem                     ; and resume
  190.  
  191. intchr: test    flags.capflg,logses     ; 'R' resume logging. Can we capture?
  192.         jz      intchr1                 ; z = no
  193.         test    targ.flgs,capt          ; already capturing?
  194.         jnz     intchr1                 ; yes, can't toggle back on then
  195.         or      targ.flgs,capt          ; else turn flag on
  196. intchr1:jmp     tem                     ; and resume
  197.  
  198. intchs: call    stat0                   ; 'S' status, call stat0
  199.         call    puthlp                  ; put help on screen
  200. ;        mov     dx,offset sttmsg
  201.         mcmsg   sttmsg,csttmsg
  202.         mov     ah,prstr
  203.         int     dos
  204. intchsa:call    iseof                   ; is stdin at eof?
  205.         jnc     intchsb                 ; nc = not eof, get more
  206.         jmp     tem                     ; resume if EOF
  207. intchsb:mov     ah,coninq               ; console input, no echo
  208.         int     dos
  209.         cmp     al,' '                  ; space?
  210.         jne     intchsa
  211.         and     targ.flgs,not scrsam    ; remember screen changed
  212.         jmp     tem
  213.  
  214. intchu: 
  215. ;------------------- Sept 21,1990 [zqf]
  216. ;       mov     ax,offset inthlp        ; '?' get help message
  217.         push    dx
  218.         mcmsg   inthlp,cinthlp
  219.         mov     ax,dx
  220.         pop     dx
  221. ;-------------------
  222.         call    puthlp                  ; write help msg
  223. ;        mov     dx,offset intprm
  224.         mcmsg   intprm,cintprm
  225.         mov     ah,prstr                ; Print it
  226.         int     dos
  227.         and     targ.flgs,not scrsam    ; remember screen changed
  228.         jmp     intchar                 ; Get another char
  229.  
  230. intchn: mov     ah,0                    ; '0' send a null
  231.         call    outchr
  232.          nop
  233.          nop
  234.          nop
  235.         jmp     tem
  236. TELNET  ENDP
  237. ; Reassure user about connection to the host. Tell him what escape sequence
  238. ; to use to return and the communications port and baud; rate being used
  239.  
  240. DOMSG   PROC    NEAR
  241.         mov     ah,prstr
  242. ;        mov     dx,offset tmsg1
  243.         mcmsg   tmsg1,ctmsg1
  244.         int     dos
  245.         call    escprt
  246.         mov     ah,prstr
  247. ;        mov     dx,offset tmsg3
  248.         mcmsg   tmsg3,ctmsg3
  249.         int     dos
  250.         ret
  251. DOMSG   ENDP
  252.  
  253. ; print the escape character in readable format.
  254.  
  255. ESCPRT  PROC    NEAR
  256.         mov     dl,trans.escchr
  257.         cmp     dl,' '
  258.         jge     escpr2
  259.         push    dx
  260.         mov     ah,prstr
  261.         mov     dx,offset esctl
  262.         int     dos
  263.         pop     dx
  264.         add     dl,040H         ; Make it printable
  265. escpr2: mov     ah,conout
  266.         int     dos
  267.         ret
  268. ESCPRT  ENDP
  269.  
  270.  
  271. ; Set parity for character in Register AL
  272.  
  273. dopar:  push    bx
  274.         mov     bx,portval
  275.         mov     bl,[bx].parflg          ; get parity flag byte
  276.         cmp     bl,parnon               ; No parity?
  277.         je      parret                  ; Just return
  278.         and     al,07FH                 ; Strip parity. Same as Space parity
  279.         cmp     bl,parspc               ; Space parity?
  280.         je      parret                  ; e = yes, then we are done here
  281.         cmp     bl,parevn               ; Even parity?
  282.         jne     dopar0                  ; ne = no
  283.         or      al,al
  284.         jpe     parret                  ; pe = even parity now
  285.         xor     al,080H                 ; Make it even parity
  286.         jmp     short parret
  287. dopar0: cmp     bl,parmrk               ; Mark parity?
  288.         jne     dopar1                  ; ne = no
  289.         or      al,080H                 ; Turn on the parity bit
  290.         jmp     short parret
  291. dopar1: cmp     bl,parodd               ; Odd parity?
  292.         or      al,al
  293.         jpo     parret                  ; Already odd, leave it
  294.         xor     al,080H                 ; Make it odd parity
  295. parret: pop     bx
  296.         ret
  297.  
  298. cptchr  proc    near                    ; session capture routine, char in al
  299.         push    di
  300.         mov     di,capbp                ; buffer pointer
  301.         mov     byte ptr [di],al
  302.         inc     capbp
  303.         pop     di
  304.         dec     caplft                  ; decrement chars remaining
  305.         jg      cptch1                  ; more room, forget this part
  306.         call    cptdmp                  ; dump the info
  307. cptch1: ret
  308. cptchr  endp
  309.  
  310. cptdmp  proc    near                    ; empty the capture buffer
  311.         push    ax
  312.         push    bx
  313.         push    cx
  314.         push    dx
  315.         mov     bx,sloghnd              ; get file handle
  316.         cmp     bx,0                    ; is file open?
  317.         jle     cptdm1                  ; le = no, skip it
  318.         mov     cx,cptsiz               ; original buffer size
  319.         sub     cx,caplft               ; minus number remaining
  320.         jl      cptdm2                  ; means error
  321.         jcxz    cptdm1                  ; z = nothing to do
  322.         mov     dx,offset capbuf        ; the capture routine buffer
  323.         mov     ah,write2               ; write with filehandle
  324.         int     dos                     ; write out the block
  325.         jc      cptdm2                  ; carry set means error
  326.         mov     capbp,offset capbuf
  327.         mov     caplft,cptsiz           ; init buffer ptr & chrs left
  328.         jmp     short cptdm1
  329. cptdm2: and     targ.flgs,not capt      ; so please stop capturing
  330. ;        mov     dx,offset erms23        ; tell user the bad news
  331.         mcmsg   erms23,cerms23
  332.         mov     ah,prstr
  333.         int     dos
  334. cptdm1: pop     dx
  335.         pop     cx
  336.         pop     bx
  337.         pop     ax
  338.         ret
  339. cptdmp  endp
  340.  
  341. pktcpt  proc    near                    ; packet log routine, char in al
  342.         push    di
  343.         mov     di,pktbp
  344.         mov     [di],al                 ; store char in buffer
  345.         inc     pktbp                   ; move pointer to next free byte
  346.         pop     di
  347.         dec     pktlft                  ; decrement chars remaining
  348.         jg      pktcp1                  ; more room, forget this part
  349.         call    pktdmp                  ; dump the info
  350. pktcp1: ret
  351. pktcpt  endp
  352.  
  353. pktdmp  proc    near                    ; empty the capture buffer
  354.         push    ax
  355.         push    bx
  356.         push    cx
  357.         push    dx
  358.         mov     bx,ploghnd              ; get file handle
  359.         cmp     bx,0                    ; is file open?
  360.         jle     cptdm1                  ; le = no, skip it
  361.         mov     cx,cptsiz               ; original buffer size
  362.         sub     cx,pktlft               ; minus number remaining
  363.         jl      pktdm2                  ; l means error
  364.         jcxz    pktdm1                  ; z = nothing to do
  365.         mov     dx,offset pktbuf        ; the capture routine buffer
  366.         mov     ah,write2               ; write with filehandle
  367.         int     dos                     ; write out the block
  368.         jc      pktdm2                  ; carry set means error
  369.         mov     pktbp,offset pktbuf
  370.         mov     pktlft,cptsiz           ; init buffer ptr & chrs left
  371.         jmp     short pktdm1
  372. pktdm2: and     targ.flgs,not capt      ; so please stop capturing
  373. ;        mov     dx,offset erms24        ; tell user the bad news
  374.         mcmsg   erms24,cerms24
  375.         mov     ah,prstr
  376.         int     dos
  377.         call    clscp4                  ; close the packet log
  378. pktdm1: pop     dx
  379.         pop     cx
  380.         pop     bx
  381.         pop     ax
  382.         ret
  383. pktdmp  endp
  384.  
  385. ; CLOSE command
  386.  
  387. clscpt  proc    near
  388.         mov     ah,cmkey
  389.         mov     dx,offset clotab        ; close table
  390. ;        mov     bx,offset clohlp        ; help
  391.         mcmsgb  clohlp,cclohlp
  392.         call    comnd
  393.          jmp    r
  394.          nop
  395.         mov     tmp,bl
  396.         mov     ah,cmcfm
  397.         call    comnd
  398.          jmp    r
  399.         mov     bl,tmp
  400.         test    flags.capflg,0FFH       ; are any kinds active?
  401.         jz      clscp1                  ; z = no
  402.         cmp     bl,logpkt+logses+logtrn ; close all?
  403.         je      clscpi                  ; e = yes
  404.         cmp     bl,logpkt               ; just packet?
  405.         je      clscp4
  406.         cmp     bl,logses               ; just session?
  407.         je      clscp6
  408.         cmp     bl,logtrn               ; just session?
  409.         jne     clscp1
  410.         jmp      clscp8
  411. clscp1: 
  412. ;       mov     dx,offset erms22        ; say none active
  413.         mcmsg   erms22,cerms22
  414.         mov     ah,prstr
  415.         int     dos
  416.         jmp     rskp
  417.                                         ; CLSCPI called at Kermit exit
  418. CLSCPI: call    clscp4                  ; close packet log
  419.         call    clscp6                  ; close session log
  420.         call    clscp8                  ; close transaction log
  421.         jmp     rskp                    ; return success
  422.  
  423. clscp4: push    bx                      ; PACKET LOG
  424.         mov     bx,ploghnd              ; packet log handle
  425.         cmp     bx,0                    ; is it open?
  426.         jle     clscp5                  ; e = no
  427.         call    pktdmp                  ; dump buffer
  428.         mov     ah,close2
  429.         int     dos
  430.         mov     ah,prstr
  431. ;        mov     dx,offset clpktlog      ; tell what we are doing
  432.         mcmsg   clpktlog,cclpktlog
  433.         int     dos
  434. clscp5: mov     ploghnd,-1              ; say handle is invalid
  435.         pop     bx
  436.         and     flags.capflg,not logpkt ; say this log is closed
  437.         ret
  438.  
  439. clscp6: push    bx                      ; SESSION LOG
  440.         mov     bx,sloghnd              ; session log handle
  441.         cmp     bx,0                    ; is it open?
  442.         jle     clscp7                  ; e = no
  443.         call    cptdmp                  ; dump buffer
  444.         mov     ah,close2
  445.         int     dos
  446.         mov     ah,prstr
  447. ;        mov     dx,offset clseslog      ; tell what we are doing
  448.         mcmsg   clseslog,cclseslog
  449.         int     dos
  450. clscp7: mov     sloghnd,-1              ; say handle is invalid
  451.         pop     bx
  452.         and     flags.capflg,not logses ; say this log is closed
  453.         ret
  454.  
  455. clscp8: push    bx                      ; TRANSACTION LOG
  456.         mov     bx,tloghnd              ; transaction log handle
  457.         cmp     bx,0                    ; is it open?
  458.         jle     clscp9                  ; e = no
  459.         mov     ah,close2
  460.         int     dos
  461.         mov     ah,prstr
  462. ;        mov     dx,offset cltrnlog      ; tell what we are doing
  463.         mcmsg   cltrnlog,ccltrnlog
  464.         int     dos
  465. clscp9: mov     tloghnd,-1              ; say handle is invalid
  466.         pop     bx
  467.         and     flags.capflg,not logtrn ; say this log is closed
  468.         ret
  469. clscpt  endp
  470.  
  471. ; worker: copy line from si to di, first removing trailing spaces, second
  472. ; parsing out curly braced strings, then third converting \{b##} in strings
  473. ; to binary numbers. Returns carry set if error; else carry clear, with byte
  474. ; count in cx. Braces are optional but must occur in pairs.
  475. ; Items which cannot be converted to legal numbers are copied verbatium
  476. ; to the output string (ex: \{c}  is copied as \{c}  but \{x0d} is hex 0dh).
  477. cnvlin  proc    near
  478.         push    ax
  479.         push    si                      ; source ptr
  480.         push    di                      ; destination ptr
  481.         push    es                      ; end of save regs
  482.         push    ds                      ; move ds into es
  483.         pop     es                      ; use datas segment for es:di
  484.         call    cnvstr                  ; trim trailing, parse curly braces
  485.         xor     cx,cx                   ; initialize returned byte count
  486. cnvln1: cmp     byte ptr [si],0         ; at end of string?
  487.         je      cnvln2                  ; e = yes, exit
  488.         call    katoi                   ; read char, convert ascii to binary
  489.         cld
  490.         stosb                           ; save the char
  491.         inc     cx                      ; and count it
  492.         or      ah,ah                   ; is returned number > 255?
  493.         jz      cnvln1                  ; z = no, do more chars
  494.         push    ax
  495.         stosb                           ; save high order byte next
  496.         pop     ax
  497.         inc     cx
  498.         jmp     short cnvln1            ; do more chars
  499. cnvln2: mov     byte ptr [di],0         ; plant terminator
  500.         clc                             ; clear c bit, success
  501. cnvlnx: pop     es                      ; restore regs
  502.         pop     di                      ; destination ptr
  503.         pop     si                      ; source ptr
  504.         pop     ax
  505.         ret
  506. cnvlin  endp
  507.  
  508. ; Convert string by first remove trailing spaces and then removing surrounding
  509. ; curly brace delimiter pair. Converts text in place.
  510. ; Enter with source ptr in si.
  511. ; Preserves all registers, uses byte tmp. 9 Oct 1987 [jrd]
  512. ;
  513. cnvstr  proc    near
  514.         push    ax
  515.         push    cx
  516.         push    dx
  517.         push    si                      ; save start of source string
  518.         push    di
  519.         push    es
  520.                                         ; 1. Trim trailing spaces
  521.         mov     dx,si                   ; source address
  522.         call    strlen                  ; get current length to cx
  523.         jcxz    cnvst4                  ; z = nothing there
  524.         mov     di,si                   ; set di to source address
  525.         add     di,cx                   ; start at end of string
  526.         dec     di                      ; ignore terminator
  527.         mov     al,spc                  ; scan while spaces
  528.         push    ds
  529.         pop     es                      ; set es to datas segment
  530.         std                             ; search backward
  531.         repe    scasb                   ; scan off trailing spaces
  532.         mov     byte ptr [di+2],0       ; terminate string after last text
  533.         cld
  534.         mov     di,si                   ; set destination address to source
  535.                                         ; 2. Parse off curly brace delimiters
  536.         cmp     byte ptr [si],braceop   ; opening brace?
  537.         jne     cnvst4                  ; ne = no, ignore brace-matching code
  538.         inc     si                      ; skip opening brace
  539.         mov     dl,braceop              ; opening brace (we count them up)
  540.         mov     dh,bracecl              ; closing brace (we count them down)
  541.         mov     tmp,1                   ; we are at brace level 1
  542. cnvst1: cld                             ; search forward
  543.         lodsb                           ; read a string char
  544.         stosb                           ; store char (skips opening brace)
  545.         cmp     al,0                    ; at end of string?
  546.         je      cnvst4                  ; e = yes, we are done
  547.         cmp     al,dl                   ; an opening brace?
  548.         jne     cnvst2                  ; ne = no
  549.         inc     tmp                     ; yes, increment brace level
  550.         jmp     short cnvst1            ;  and continue scanning
  551.  
  552. cnvst2: cmp     al,dh                   ; closing brace?
  553.         jne     cnvst1                  ; ne = no, continue scanning
  554.         dec     tmp                     ; yes, decrement brace level
  555.         cmp     byte ptr [si],0         ; have we just read the last char?
  556.         jne     cnvst3                  ; no, continue scanning
  557.         mov     tmp,0                   ; yes, this is the closing brace
  558. cnvst3: cmp     tmp,0                   ; at level 0?
  559.         jne     cnvst1                  ; ne = no, #opening > #closing braces
  560.         mov     byte ptr [di-1],0       ; plant terminator on closing brace
  561.  
  562. cnvst4: pop     es                      ; recover original registers
  563.         pop     di
  564.         pop     si
  565.         pop     dx
  566.         pop     cx
  567.         pop     ax
  568.         ret
  569. cnvstr  endp
  570.  
  571. ; Convert ascii strings of the form "\{bnnn}" to a binary word in ax.
  572. ; The braces are optional but must occur in pairs. Numeric base indicator "b"
  573. ; is O or o or X or x or D or d or missing, for octal, hex, or decimal (def).
  574. ; Enter with si pointing at "\".
  575. ; Returns binary value in ax with carry clear and si to right of "}" or at
  576. ; terminating non-numeric char if successful; otherwise, a failure,
  577. ; return carry set with si = entry value + 1 and first read char in al.
  578.  
  579. katoi   proc    near
  580.         cld
  581.         lodsb                           ; get first char
  582.         xor     ah,ah                   ; clear high order field
  583.         push    cx                      ; save working reg
  584.         push    si                      ; save entry si+1
  585.         push    bx
  586.         push    ax                      ; save read char
  587. KATOI1: cmp     al,0                    ; end of text? ENTRY POINT FOR ATOI
  588.         je      katoi1a                 ; e = yes, exit failure
  589.         cmp     al,'\'                  ; escape char?
  590.         je      katoi1b                 ; e = yes
  591. katoi1a:jmp     katoix                  ; common jump point to exit failure
  592. katoi1b:lodsb                           ; get next char, maybe brace
  593.         cmp     al,0                    ; premature end?
  594.         je      katoi1a                 ; e = yes, exit failure
  595.         xor     bx,bx                   ; no conv yet, assume no opening brace
  596.         cmp     al,braceop              ; opening brace?
  597.         jne     katoi2                  ; ne = no, have number or base
  598.         mov     bl,bracecl              ; remember a closing brace is needed
  599.         lodsb                           ; get number base, if any
  600. katoi2: xor     cx,cx                   ; temporary place for binary value
  601.         mov     nbase,10                ; assume decimal numbers
  602.         cmp     al,0                    ; premature end?
  603.         je      katoix                  ; e = yes, exit failure
  604.         cmp     al,'a'                  ; lower case?
  605.         jb      katoi3                  ; b = no
  606.         cmp     al,'z'                  ; in range of lower case?
  607.         ja      katoi3                  ; a = no
  608.         and     al,5fh                  ; map to upper case
  609. katoi3: cmp     al,'O'                  ; octal?
  610.         jne     katoi4                  ; ne = no
  611.         mov     nbase,8                 ; set number base
  612.         jmp     short katoi6
  613. katoi4: cmp     al,'X'                  ; hex?
  614.         jne     katoi5                  ; ne = no
  615.         mov     nbase,16
  616.         jmp     short katoi6
  617. katoi5: cmp     al,'D'                  ; decimal?
  618.         jne     katoi7                  ; ne = no base char, assume decimal
  619.         mov     nbase,10
  620. katoi6: lodsb                           ; get a digit
  621. katoi7: cmp     al,0                    ; premature end?
  622.         je      katoi8a                 ; e = yes, use it as a normal end
  623.         cmp     al,bl                   ; closing brace?
  624.         je      katoi9                  ; e = yes
  625.         call    cnvdig                  ; convert ascii to binary digit
  626.         jc      katoi8                  ; c = cannot convert
  627.         inc     bh                      ; say we did a successful conversion
  628.         xor     ah,ah                   ; clear high order value
  629.         push    ax                      ; save this byte's value
  630.         xchg    ax,cx                   ; put binary summation in ax
  631.         mul     nbase                   ; scale up current sum
  632.         xchg    ax,cx                   ; put binary back in cx
  633.         pop     ax                      ; recover binary digit
  634.         add     cx,ax                   ; form running sum
  635.         jc      katoix                  ; c = overflow error, exit
  636.         cmp     dx,0                    ; overflow?
  637.         jne     katoix                  ; ne = yes, exit with error
  638.         jmp     short katoi6            ; get more
  639.  
  640. katoi8: cmp     bl,0                    ; closing brace needed?
  641.         jne     katoix                  ; ne = yes, but not found
  642. katoi8a:dec     si                      ; backup to reread terminator
  643. katoi9: cmp     bh,0                    ; did we do any conversion?
  644.         je      katoix                  ; e = no, exit failure
  645.         pop     ax                      ; throw away old saved ax
  646.         pop     bx                      ; restore bx
  647.         pop     ax                      ; throw away starting si, keep current
  648.         mov     ax,cx                   ; return final value in ax
  649.         pop     cx                      ; restore old cx
  650.         clc                             ; clear carry for success
  651.         ret
  652. katoix: pop     ax                      ; restore first read al
  653.         pop     bx
  654.         pop     si                      ; restore start value + 1
  655.         pop     cx                      ; restore old cx
  656.         stc                             ; set carry for failure
  657.         ret
  658. katoi   endp
  659.  
  660. cnvdig  proc    near                    ; convert ascii code in al to binary
  661.         push    cx                      ; return carry set if cannot
  662.         push    es                      ; nbase has numeric base
  663.         push    di
  664.         push    ax
  665.         cmp     al,'a'                  ; lower case?
  666.         jb      cnvdig1                 ; b = no
  667.         cmp     al,'f'                  ; highest hex digit
  668.         ja      cnvdigx                 ; a = illegal symbol
  669.         sub     al,'a'-'A'              ; convert 'a' to 'f' to upper case
  670. cnvdig1:mov     di,offset numset        ; set of legal number symbols
  671.         mov     cx,nbase                ; number of legal symbols in this base
  672.         cmp     cx,cx                   ; preset z flag
  673.         push    ds
  674.         pop     es                      ; point es at data segment
  675.         cld                             ; scan forward
  676.         repne   scasb                   ; find character in set
  677.         jne     cnvdigx                 ; ne = not found
  678. cnvdig2:inc     cx                      ; offset auto-dec of repne scasb above
  679.         sub     cx,nbase                ; counted off minus length
  680.         neg     cx                      ; two's complement = final value
  681.         pop     ax                      ; saved ax
  682.         mov     ax,cx                   ; return binary in al
  683.         clc                             ; c clear for success
  684.         jmp     short cnvdixx           ; exit
  685. cnvdigx:stc                             ; c set for failure
  686.         pop     ax
  687. cnvdixx:pop     di
  688.         pop     es
  689.         pop     cx
  690.         ret
  691. cnvdig  endp
  692.  
  693. decout  proc    near            ; display decimal number in ax
  694.         push    ax
  695.         push    cx
  696.         push    dx
  697.         mov     cx,10           ; set the numeric base
  698.         call    valout          ; convert and output value
  699.         pop     dx
  700.         pop     cx
  701.         pop     ax
  702.         ret
  703. decout  endp
  704.  
  705. valout  proc    near            ; output number in ax using base in cx
  706.                                 ; corrupts ax and dx
  707.         xor     dx,dx           ; clear high word of numerator
  708.         div     cx              ; (ax / cx), remainder = dx, quotient = ax
  709.         push    dx              ; save remainder for outputting later
  710.         or      ax,ax           ; any quotient left?
  711.         jz      valout1         ; z = no
  712.         call    valout          ; yes, recurse
  713. valout1:pop     dx              ; get remainder
  714.         add     dl,'0'          ; make digit printable
  715.         cmp     dl,'9'          ; above 9?
  716.         jbe     valout2         ; be = no
  717.         add     dl,'A'-1-'9'    ; use 'A'--'F' for values above 9
  718. valout2:mov     ah,conout
  719.         int     dos
  720.         ret
  721. valout  endp
  722.  
  723. ; Convert input in buffer pointed to by SI to real number which is returned
  724. ; in AX.  Enter with string size in AH.
  725. ; Return on failure, return skip on success.      Revised by [jrd]
  726. ATOI    PROC    NEAR
  727.         mov     bx,0            ; high order of this stays 0
  728.         mov     tmp,0           ; No input yet
  729.         mov     cl,ah           ; Number of chars of input
  730.         mov     ch,0            ; size of string
  731.         mov     ax,0            ; init sum
  732.         cld
  733. atoi0:  jcxz    atoi4           ; Fail on no input
  734.         lodsb                   ; get an input char
  735.         dec     cx              ; count number remaining
  736.         cmp     al,' '          ; leading space?
  737.         je      atoi0           ; e = yes, skip it
  738.         cmp     al,','          ; comma separator?
  739.         je      atoi0           ; e = yes, skip it
  740.         dec     si              ; back up source pointer for reread below
  741.         inc     cx              ; and readjust byte counter
  742.         mov     ax,0            ; clear sum
  743. atoi1:  push    ax              ; save sum
  744.         lodsb                   ; read a byte into al
  745.         mov     bl,al           ; put it into bl
  746.         pop     ax              ; regain sum
  747.         cmp     bl,'9'          ; check range for '0' to '9'
  748.         ja      atoi2           ; above '9'
  749.         cmp     bl,'0'
  750.         jb      atoi2           ; below '0'
  751.         sub     bl,'0'          ; take away ascii bias
  752.         mul     ten             ; sum * 10. dx = high, ax = low
  753.         add     ax,bx           ; add current value
  754.         mov     tmp,1           ; say have sum being computed
  755.         loop    atoi1
  756.         inc     si              ; inc for dec below
  757. atoi2:  dec     si              ; point at terminator
  758.         cmp     tmp,0           ; were any digits discovered?
  759.         je      atoi4           ; e = no, fail
  760. atoi3:  jmp     rskp            ; success exit, sum is in ax
  761. atoi4:  
  762. ;       mov     dx,offset erms25 ; Input must be numeric
  763.         mcmsg   erms25,cerms25
  764.         ret
  765. ATOI    ENDP
  766.  
  767. ; Jumping to this location is like retskp.  It assumes the instruction
  768. ;   after the call is a jmp addr.
  769.  
  770. RSKP    PROC    NEAR
  771.         pop     bp
  772.         add     bp,3
  773.         push    bp
  774.         ret
  775. RSKP    ENDP
  776.  
  777. ; Jumping here is the same as a ret
  778.  
  779. R       PROC    NEAR
  780.         ret
  781. R       ENDP
  782.  
  783. code    ends
  784.         end
  785.