home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 01e / msk230s2.zip / MSSTER.ASM next >
Assembly Source File  |  1988-02-12  |  35KB  |  751 lines

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