home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / mssset.asm < prev    next >
Assembly Source File  |  2020-01-01  |  142KB  |  4,783 lines

  1.     NAME    mssset
  2. ; File MSSSET.ASM
  3.     include mssdef.h
  4. ;    Copyright (C) 1982, 1997, Trustees of Columbia University in the 
  5. ;    City of New York.  The MS-DOS Kermit software may not be, in whole 
  6. ;    or in part, licensed or sold for profit as a software product itself,
  7. ;    nor may it be included in or distributed with commercial products
  8. ;    or otherwise distributed by commercial concerns to their clients 
  9. ;    or customers without written permission of the Office of Kermit 
  10. ;    Development and Distribution, Columbia University.  This copyright 
  11. ;    notice must not be removed, altered, or obscured.
  12. ;
  13. ; Edit history
  14. ; 12 Jan 1995 version 3.14
  15. ; Last edit
  16. ; 12 Jan 1995
  17.  
  18.     public    setcom, prmptr, dodef, setcpt, docom, stkadr, rdbuf, reset
  19.     public    setrx, rxtable, srvdsa, srvena, mcctab, takclos, ask
  20.     public    askq, assign, initibm, mccptr, setinpbuf, setrollb, npages
  21.     public    xfchtab, xftyptab, com1port, com2port, com3port, com4port
  22.     public    flotab, popcmd, domacptr, warntab, portirq, portfifo, dodecom
  23.     public    xfertab1, xfertab2, xfertab3, rollwidth, setwidth, abftab
  24.     public    localmac, getok, takeerror, macroerror, getc, dial, docnv
  25.     public    takopen_sub, takopen_file, takopen_macro, _forinc, poplevel
  26.     public    hide_assign, hide_define, declare, marray, forcmd, undefine
  27. ifndef    no_tcp
  28.     public    tcpaddress,tcpsubnet,tcpdomain,tcpgateway,tcpprimens
  29.     public    tcpsecondns,tcphost,tcpbcast,tcpport,tcppdint,tcpttbuf
  30.     public    tcpbtpserver,tcpnewline,tcpdebug,tcpmode,tcpmss
  31. endif    ; no_tcp
  32.  
  33. braceop    equ    7bh        ; opening curly brace
  34. bracecl    equ    7dh        ; closing curly brace
  35.  
  36. maketab    MACRO            ; Assembler Macro to make rxtable [jrd]
  37. cnt = 0
  38.     rept 256
  39.     db    cnt        ; initialize table to 0 .. 255
  40. cnt = cnt + 1
  41.     endm
  42.     db    0        ; table off (0) or on (1) indicator
  43. ENDM
  44.  
  45. data     segment
  46.     extrn    comand:byte, flags:byte, trans:byte, takadr:word, taklev:byte
  47.     extrn    portval:word, dtrans:byte, spause:word, machnam:byte
  48.     extrn    filtst:byte, maxtry:byte, script:byte, denyflg:word
  49.     extrn    sloghnd:word, ploghnd:word, tloghnd:word, cardet:byte
  50.     extrn    decbuf:byte, kstatus:word, errlev:byte, srvtmo:byte
  51.     extrn    luser:byte, lpass:byte, destab:byte, blktab:byte
  52.     extrn    seoftab:byte, dmpname:byte, lsesnam:byte, lpktnam:byte
  53.     extrn    ltranam:byte, incstb:byte, inactb:byte, rxoffmsg:byte
  54.     extrn    rxonmsg:byte, scpbuflen:word, setchtab:byte
  55.     extrn    prnname:byte, prnhand:word, outpace:word, apctrap:byte
  56.     extrn    protlist:byte, rcvpathflg:byte, sndpathflg:byte
  57.     extrn    fossilflag:byte, ifelse:byte, oldifelse:byte
  58.     extrn    domath_ptr:word, domath_cnt:word, domath_msg:word
  59.  
  60. rxtable    equ THIS BYTE        ; build 256 byte Translation Input table
  61.     maketab            ; table rxtable is used by Connect mode
  62.  
  63. kerm    db    'MS-Kermit>',0        ; default ASCIIZ prompt
  64. promptbuf db    80 dup (0),0        ; buffer for new ASCIIZ prompt
  65. rdbuf    db    cmdblen dup (?)        ; work space; room for macro def
  66.                     ;  and for Status display line
  67. settemp db    100 dup (0)    ; temp for hidemac/unhide
  68. stflg    db    0        ; Says if setting SEND or RECEIVE parameter
  69. defkind    db    0        ; 0 for ASSIGN, 1 for DEFINE
  70. ermes1    db    cr,lf,'?Too many macro names$'
  71. ermes2    db    cr,lf,bell,'?No room for Take file buffer or Macro definition'
  72.     db    cr,lf,bell,'$'
  73. ermes4    db    cr,lf,'?Too many active Take files and Macros',cr,lf, bell,'$'
  74. ermes5    db    cr,lf,'?Not implemented$'
  75. ermes6    db    cr,lf,'?More parameters are needed$'
  76. ermes7    db    cr,lf,'?Cannot use RTS/CTS on non-UART ports$'
  77. ermes8    db    cr,lf,'?Cannot use HARDWARE parity on non-UART ports$'
  78. errcap    db    cr,lf,'?Unable to open that file$'
  79. erropn    db    cr,lf,'?Log file is already open$'
  80. badrx    db    cr,lf,'?Expected ON, OFF, or \nnn$'
  81. escerr    db    cr,lf,'?Not a control code$'
  82. takcerr    db    cr,lf,'?Note: command is valid only in Take files and Macros$'
  83. dmpdefnam db    'Kermit.scn',0        ; asciiz default screen dump filename
  84. prndefnam db    'PRN',0            ; asciiz default printer name
  85. xfchbad    db    cr,lf,'Warning: forcing FILE CHARACTER-SET to CP866$'
  86. xfchbad2 db    cr,lf,'Warning: forcing FILE CHARACTER-SET to Shift-JIS$'
  87. xfchbad3 db    cr,lf,'Warning: forcing FILE CHARACTER-SET to CP862$'
  88. setchmsg db    cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to CYRILLIC$'
  89. setchmsg2 db    cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to'
  90.     db    ' Japanese-EUC$'
  91. setchmsg3 db  cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to HEBREW-ISO$'
  92. badcntlmsg db    cr,lf,'?Number is not in range of 0..31, 128..159$'
  93. getdef    db    'Please respond Yes or No ',0    ; ASCII, used as prompt
  94. crlf    db    cr,lf,'$'
  95. space    db    ' ',0
  96.  
  97. srvtab    db    2            ; SET SERVER table
  98.     mkeyw    'Login',1
  99.     mkeyw    'Timeout',2
  100.  
  101. ifndef    no_network
  102. settab     db    63                    ; Set table
  103. else
  104. settab     db    63 - 3                    ; Set table
  105. endif    ; no_network
  106.     mkeyw    'Alarm',setalrm
  107.     mkeyw    'Attributes',setatt
  108.     mkeyw    'Baud',baudst
  109.     mkeyw    'Bell',bellst
  110.     mkeyw    'Block-check-type',blkset
  111.     mkeyw    'Carrier',setcar
  112.     mkeyw    'COM1',com1port
  113.     mkeyw    'COM2',com2port
  114.     mkeyw    'COM3',com3port
  115.     mkeyw    'COM4',com4port
  116.     mkeyw    'Control-character',cntlset
  117.     mkeyw    'Count',takectr
  118.     mkeyw    'Debug',debst
  119.     mkeyw    'Default-disk',cwdir
  120.     mkeyw    'Delay',setdely
  121.     mkeyw    'Destination',desset
  122.     mkeyw    'Display',disply
  123.     mkeyw    'Dump',setdmp
  124.     mkeyw    'Duplex',setdup
  125.     mkeyw    'End-of-Line',eolset
  126.     mkeyw    'EOF',seteof
  127.     mkeyw    'Errorlevel',seterl
  128.     mkeyw    'Escape-character',escset
  129.     mkeyw    'Exit',setexitwarn
  130.     mkeyw    'File',setfile
  131.     mkeyw    'Flow-control',floset
  132.     mkeyw    'Fossil',fosset
  133.     mkeyw    'Handshake',hndset
  134.     mkeyw    'Incomplete',abfset
  135.     mkeyw    'Input',inpset
  136.     mkeyw    'Key',setkey
  137.     mkeyw    'Line',coms
  138.     mkeyw    'Local-echo',lcal
  139.     mkeyw    'Macro',setmacerr
  140.     mkeyw    'Mode-line',modl
  141.     mkeyw    'Modem',setmodem
  142. ifndef    no_network
  143.     mkeyw    'NetBios-name',setnbios
  144. endif    ; no_network
  145.     mkeyw    'Output',setoutput
  146.     mkeyw    'Parity',setpar
  147.     mkeyw    'Port',coms
  148.     mkeyw    'Printer',setprn
  149.     mkeyw    'Prompt',promset
  150.     mkeyw    'Receive',recset
  151.     mkeyw    'Remote',remset
  152.     mkeyw    'Repeat',repset
  153.     mkeyw    'Retry',retryset
  154.     mkeyw    'Rollback',setrollb
  155.     mkeyw    'Send',sendset
  156.     mkeyw    'Server',setsrv
  157.     mkeyw    'Speed',baudst
  158.     mkeyw    'Stop-bits',stopbit
  159.     mkeyw    'Take',takset
  160. ifndef    no_tcp
  161.     mkeyw    'TCP/IP',tcpipset
  162.     mkeyw    'Telnet',tcpipset
  163. endif    ; no_tcp
  164.     mkeyw    'Terminal',vts
  165.     mkeyw    'Timer',timset
  166.     mkeyw    'Transfer',sxfer
  167.     mkeyw    'xfer',sxfer        ; hidden synonym
  168.     mkeyw    'Translation',setrx
  169.     mkeyw    'Transmit',setxmit
  170.     mkeyw    'Unknown-character-set',unkchset
  171.     mkeyw    'Warning',filwar
  172.     mkeyw    'Windows',winset
  173.  
  174. setfitab db    6            ; Set File command table
  175.     mkeyw    'Character-Set',1
  176.     mkeyw    'Collision',0
  177.     mkeyw    'Display',3
  178.     mkeyw    'Incomplete',4
  179.     mkeyw    'Type',2
  180.     mkeyw    'Warning',0
  181.  
  182. setrep    db    2            ; SET REPEAT
  183.     mkeyw    'Counts',0
  184.     mkeyw    'Prefix',1
  185.  
  186. xfertab    db    4            ; SET TRANSFER table
  187.     mkeyw    'Character-set',0
  188.     mkeyw    'Locking-shift',1
  189.     mkeyw    'Mode',3
  190.     mkeyw    'Translation',2
  191.  
  192. xfertab1 db    3            ; SET TRANSFER LOCKING-SHIFT
  193.     mkeyw    'Off',lock_disable
  194.     mkeyw    'On',lock_enable
  195.     mkeyw    'Forced',lock_force
  196.  
  197. xfertab2 db    2            ; SET TRANSFER TRANSLATION
  198.     mkeyw    'Readable',0
  199.     mkeyw    'Invertible',1
  200.  
  201. xfertab3 db    2            ; SET TRANSFER MODE
  202.     mkeyw    'Automatic',1
  203.     mkeyw    'Manual',0
  204.  
  205. xfchtab    db    6            ; SET TRANSFER CHARACTER-SET
  206.     mkeyw    'Transparent',xfr_xparent    ; no translation
  207.     mkeyw    'Latin1 ISO 8859-1',xfr_latin1    ; ISO 8859-1, Latin-1
  208.     mkeyw    'Latin2 ISO 8859-2',xfr_latin2    ; ISO 8859-2, Latin-2
  209.     mkeyw    'Hebrew ISO 8859-8',xfr_hebiso    ; ISO 8859-8 Hebrew-ISO
  210.     mkeyw    'Cyrillic ISO 8859-5',xfr_cyrillic; ISO 8859-5/Cyrillic, CP866
  211.     mkeyw    'Japanese-EUC',xfr_japanese    ; Japanese-EUC
  212.  
  213. xftyptab db    2            ; SET FILE TYPE table
  214.     mkeyw    'Binary',1        ; Binary = as-is
  215.     mkeyw    'Text',0        ; Text = can change char sets
  216.  
  217. warntab    db    8            ; File Warning table
  218.     mkeyw    'Append',filecol_append        ; append
  219.     mkeyw    'Overwrite',filecol_overwrite    ; overwrite
  220.     mkeyw    'Rename',filecol_rename        ; rename
  221.     mkeyw    'Discard',filecol_discard    ; discard
  222.     mkeyw    'Update',filecol_update        ; update (if incoming is newer)
  223.     mkeyw    'No-supersede',filecol_discard    ; discard
  224.     mkeyw    'on (rename)',filecol_rename    ; old form
  225.     mkeyw    'off (overwrite)',filecol_overwrite ; old form
  226.  
  227. unkctab db    2            ; unknown character-set disposition
  228.     mkeyw    'Keep',0
  229.     mkeyw    'Cancel',1
  230.  
  231. atttab    db    7            ; SET ATTRIBUTES table
  232.     mkeyw    'Off',00ffh        ; all off
  233.     mkeyw    'On',10ffh        ; all on (high byte is on/off)
  234.     mkeyw    'Character-set',attchr    ; Character set
  235.     mkeyw    'Date-Time',attdate    ; Date and Time
  236.     mkeyw    'Length',attlen        ; Length
  237.     mkeyw    'Type',atttype        ; Type
  238.     mkeyw    'System-id',attsys    ; System
  239.  
  240. comtab    db    2            ; table of COM ports
  241.     mkeyw    'COM3',4        ; offset of COM3 address
  242.     mkeyw    'COM4',6        ; offset of COM4 address
  243.  
  244. cntltab    db    2            ; SET CONTROL table
  245.     mkeyw    'Prefixed',0        ; 0 = send with prefix
  246.     mkeyw    'Unprefixed',1        ; 1 = send as-is
  247.  
  248. stsrtb    db    11            ; Number of options
  249.     mkeyw    'Packet-length',srpack
  250.     mkeyw    'Padchar',srpad
  251.     mkeyw    'Padding',srnpd
  252.     mkeyw    'Pause',srpaus
  253.     mkeyw    'Start-of-packet',srsoh
  254.     mkeyw    'Quote',srquo
  255.     mkeyw    'End-of-packet',sreol
  256.     mkeyw    'Timeout',srtim
  257.     mkeyw    'Double-char',srdbl
  258.     mkeyw    'Ignore-char',srign
  259.     mkeyw    'Pathnames',srpath
  260.  
  261. ontab    db    2
  262.     mkeyw    'off',0
  263.     mkeyw    'on',1
  264.  
  265. outputtab db    1            ; Set OUTPUT
  266.     mkeyw    'PACING',setopace
  267.  
  268. distab    db    5             ; Set Display mode
  269.     mkeyw    '7-bit',7        ; controls bit d8bit in flags.remflg
  270.     mkeyw    '8-bit',8        ; sets d8bit
  271.     mkeyw    'Quiet',dquiet        ; values defined in header file
  272.     mkeyw    'Regular',dregular
  273.     mkeyw    'Serial',dserial
  274.  
  275. distab2    db    3            ; for SET FILE DISPLAY
  276.     mkeyw    'Quiet',dquiet        ; values defined in header file
  277.     mkeyw    'Regular',dregular
  278.     mkeyw    'Serial',dserial
  279.  
  280. fossiltab db    1            ; Fossil
  281.     mkeyw    'disable-on-close',1
  282.  
  283. ; If abort when receiving files, can keep what we have or discard
  284. abftab    db    2
  285.     mkeyw    'Discard',1
  286.     mkeyw    'Keep',0
  287.  
  288. flotab    db    5
  289.     mkeyw    'none',0
  290.     mkeyw    'xon/xoff',1+2        ; both directions
  291.     mkeyw    'incoming-xon/xoff',2
  292.     mkeyw    'outgoing-xon/xoff',1
  293.     mkeyw    'RTS/CTS',4
  294.  
  295. FIFOtab    db    2
  296.     mkeyw    'FIFO-disabled',0
  297.     mkeyw    'FIFO-enabled',1
  298.  
  299. hndtab    db    8
  300.     mkeyw    'none',0
  301.     mkeyw    'bell',bell
  302.     mkeyw    'cr',cr
  303.     mkeyw    'esc',escape
  304.     mkeyw    'lf',lf
  305.     mkeyw    'xoff',xoff
  306.     mkeyw    'xon',xon
  307.     mkeyw    'code',0ffh        ; allow general numerial code
  308.  
  309. duptab    db    2            ; SET DUPLEX table
  310.     mkeyw    'full',0
  311.     mkeyw    'half',1
  312.  
  313. partab    db    6
  314.     mkeyw    'none',PARNON
  315.     mkeyw    'even',PAREVN
  316.     mkeyw    'odd',PARODD
  317.     mkeyw    'mark',PARMRK
  318.     mkeyw    'space',PARSPC
  319.     mkeyw    'HARDWARE',PARHARDWARE
  320. parhwtab db    4            ; for 9-bit bytes
  321.     mkeyw    'even',PAREVNH
  322.     mkeyw    'odd',PARODDH
  323.     mkeyw    'mark',PARMRKH
  324.     mkeyw    'space',PARSPCH
  325.  
  326. exittab    db    1            ; EXIT table
  327.     mkeyw    'warning',0
  328.  
  329. gettab    db    3            ; GETOK dispatch table
  330.     mkeyw    'Yes',kssuc        ; success = yes
  331.     mkeyw    'OK',kssuc        ; ditto
  332.     mkeyw    'No',ksgen        ; general failure
  333.  
  334. inptab    db    5                ; Scripts. Set Input
  335.     mkeyw    'Case',inpcas            ;[jrs]
  336.     mkeyw    'Default-timeout',inptmo    ;[jrs]
  337.     mkeyw    'Echo',inpeco            ;[jrs]
  338.     mkeyw    'Filter-echo',infilt
  339.     mkeyw    'Timeout-action',inpact        ;[jrs]
  340.  
  341. resettab db    1
  342.     mkeyw    'Clock',80h
  343.  
  344. macrotab db    1            ; SET MACRO table
  345. ;;    mkeyw    'Echo',0
  346.     mkeyw    'Error',1
  347.  
  348. taketab    db    2            ; SET TAKE table
  349.     mkeyw    'Echo',0
  350.     mkeyw    'Error',1
  351.  
  352. xmitab    db    4            ; SET TRANSMIT table
  353.     mkeyw    'Fill-empty-line',0
  354.     mkeyw    'Line-Feeds-sent',1
  355.     mkeyw    'Pause',3
  356.     mkeyw    'Prompt',2
  357.  
  358. debtab    db    4            ; Set Debug command
  359.     mkeyw    'Off',0
  360.     mkeyw    'On',logpkt+logses
  361.     mkeyw    'Packets',logpkt
  362.     mkeyw    'Session',logses
  363.  
  364. logtab    db    3            ; LOG command
  365.     mkeyw    'Packets',logpkt
  366.     mkeyw    'Session',logses
  367.     mkeyw    'Transactions',logtrn
  368.  
  369. srvdetab db    17            ; Server Enable/Disable list
  370.     mkeyw    'All',0fffh
  371.     mkeyw    'CD',cwdflg
  372.     mkeyw    'CWD',cwdflg
  373.     mkeyw    'Define',defflg
  374.     mkeyw    'Delete',delflg
  375.     mkeyw    'Dir',dirflg
  376.     mkeyw    'Finish',finflg
  377.     mkeyw    'Get',getsflg
  378.     mkeyw    'Host',hostflg
  379.     mkeyw    'Kermit',kerflg
  380.     mkeyw    'Login',pasflg
  381.     mkeyw    'Print',prtflg
  382.     mkeyw    'Retrieve',retflg
  383.     mkeyw    'Query',qryflg
  384.     mkeyw    'Send',sndflg
  385.     mkeyw    'Space',spcflg
  386.     mkeyw    'Type',typflg
  387.  
  388. trnstab    db    2            ; Set Translation table
  389.     mkeyw    'Input',1
  390.     mkeyw    'Keyboard',2
  391.  
  392. ifndef    no_tcp
  393. tcptable db    14            ; Telnet or TCP/IP command
  394.     mkeyw    'address',1        ; local Internet address
  395.     mkeyw    'domain',2        ; local domain string
  396.     mkeyw    'broadcast',8        ; broadcast of all 0's or all 1's
  397.     mkeyw    'gateway',4        ; gateway address
  398.     mkeyw    'primary-nameserver',5    ; name servers
  399.     mkeyw    'secondary-nameserver',6
  400.     mkeyw    'subnetmask',3        ; our subnet mask
  401.     mkeyw    'host',7        ; host's IP name or IP number
  402.     mkeyw    'Packet-Driver-interrupt',9
  403.     mkeyw    'term-type',10        ; Options term type
  404.     mkeyw    'NewLine-mode',11     ; CR-NUL vs CRLF
  405.     mkeyw    'mode',13        ; NVT-ASCII or Binary
  406.     mkeyw    'mss',14        ; Max Segment Size
  407.     mkeyw    'debug-Options',12    ; debug Telnet Options
  408.  
  409. tcpmodetab db    2            ; TCP/IP Mode
  410.     mkeyw    'NVT-ASCII',0
  411.     mkeyw    'Binary',1
  412.  
  413. newlinetab db    3            ; TCP/IP Newline mode
  414.     mkeyw    'off',0
  415.     mkeyw    'on',1
  416.     mkeyw    'raw',2
  417.  
  418. domainbad db    cr,lf,'?Bad domain name, use is such as my.domain.name$'
  419. addressbad db    cr,lf,'?string is too long$'
  420. hostbad    db    cr,lf,'?Bad host, use IP name or IP number$'
  421.  
  422. tcpaddress db    'dhcp',(16-($-tcpaddress)) dup (0),0
  423. tcpsubnet  db    '255.255.255.0',(16-($-tcpsubnet)) dup (0),0
  424. tcpdomain  db    'unknown',(32-($-tcpdomain)) dup (0),0
  425. tcpgateway db    'unknown',(32-($-tcpgateway)) dup (0),0
  426. tcpprimens db    'unknown',(16-($-tcpprimens)) dup (0),0
  427. tcpsecondns db    'unknown',(16-($-tcpsecondns)) dup (0),0
  428. tcphost    db    (60 -($-tcphost)) dup (0),0
  429. tcpbcast db    '255.255.255.255',(16-($-tcpbcast)) dup (0),0
  430. tcpbtpserver db    17 dup (0)        ; bootp server (response)
  431. tcpport    dw    23            ; TCP port
  432. tcppdint dw    0            ; Packet Driver interrupt
  433. tcpttbuf db    32 dup (0),0        ; term-type-override buffer
  434. tcpnewline db    1            ; NewLine-Mode (default is on)
  435. tcpdebug db    0            ; Options debugging (0 is off)
  436. tcpmode db    0            ; NVT-ASCII is 0, Binary is 1
  437. tcpmss    dw    1460            ; MSS
  438. endif    ; no_tcp
  439.  
  440. ; MACRO DATA STRUCTURES mcctab
  441. mcclen    equ    macmax*10        ; length of mcctab
  442. mcctab    db    0            ; macro name table entries
  443.     db    mcclen dup (0)        ; room for macro structures
  444. ; END OF MACRO DATA STRUCTURES
  445.  
  446. ibmmac    db    'IBM '            ; startup IBM macro definition + space
  447.     db    'set timer on,set parity mark,set local-echo on,'
  448.     db    'set handshake xon,set flow none,',0    ; asciiz
  449. dialmac    db    '__DIAL '            ; "__DIAL "
  450.     db    'asg \%9 \v(carrier),set carr off,'
  451.     db    'output ATD\%1\%2\%3\%4\%5\%6\%7\%8\13,wait 90 CD,'
  452.     db    'asg \%8 \v(status),set carr \%9,end \%8,',0    ; asciiz
  453.  
  454.     even
  455. prmptr    dw    kerm            ; pointer to prompt
  456. tempptr    dw    0            ; pointer into work buffer
  457. domacptr dw    0            ; pointer to DO MAC string
  458. min    dw    0 
  459. max    dw    0 
  460. numerr    dw    0
  461. numhlp    dw    0
  462. temp    dw    0
  463. temp1    dw    0            ; Temporary storage
  464. temp2    dw    0            ; Temporary storage
  465. askecho db    0            ; ask's echo control flag
  466. deftemp    dw    0
  467. stkadr    dw    0    ; non-zero if replacement keyboard xlator present
  468. mccptr    dw    mcctab             ; ptr to first free byte in mcctab
  469. macptr    dw    0            ; temp to hold segment of string
  470. npages    dw    10             ; # of pages of scrolling on each side
  471. rollwidth dw    0            ; columns to roll back 80..207
  472. portirq    db    4 dup (0)        ; user specified IRQ's for COM1..4
  473. portfifo db    4 dup (1)        ; user specified FIFO for COM1..4
  474. takeerror db    0            ; Take Error (0 = off)
  475. macroerror db    0            ; Macro Error (0 = off)
  476. marray    dw    27 dup (0)        ; pointers to macro array mem areas
  477. arraybad db    cr,lf,'? Array size is too large, 32000 max$'
  478.  
  479. forstr1    db    '_forinc ',0         ; append 'variable step'
  480. forstr2 db    ' if not > ',0        ; append 'variable end'
  481. forstartptr dw    0
  482. forendptr dw    0
  483. forstepptr dw    0
  484. forcmdsptr dw 0
  485. forbadname db    cr,lf,'?Not a variable name$'
  486. data    ends
  487.  
  488. data1    segment
  489. askhlp1    db    'Variable name  then  prompt string$'
  490. askhlp2    db    'Prompt string$'
  491. askhlp3    db    'Enter a line of text$'
  492. getokhlp db    'Optional prompt string$'
  493. filhlp    db    ' Output filename for the log$'
  494. forhlp    db    cr,lf,'FOR variable initial final increment'
  495.     db    ' {command,command,...}$'
  496. dishlp    db    cr,lf,' Quiet (no screen writing), Regular (normal),'
  497.     db    ' Serial (non-formatted screen)'
  498.     db    cr,lf,' and/or 7-BIT (default) or 8-BIT wide characters.$'
  499. exitwhlp db    cr,lf,' ON or OFF. Warn if sessions are active when exiting'
  500.     db    ' Kermit$'
  501. remhlp    db    cr,lf,' OFF to show file transfer display,'
  502.     db    ' ON for quiet screen$'
  503. macmsg    db    ' Specify macro name followed by body of macro, on same line$'
  504. prmmsg    db    cr,lf
  505.     db    ' Enter new prompt string or press Enter to regain default prompt.'
  506.     db    cr,lf,' Use \fchar(123) notation for special chars;'
  507.     db    ' Escape is \fchar(27).$'
  508. rspathhlp db    cr,lf,' ON retains pathnames during file transfer,'
  509.     db    ' OFF removes them$'
  510.     
  511. srxhlp1    db    cr,lf,' Enter   code for received byte   code for'
  512.     db    ' local byte ',cr,lf,' use ascii characters themselves or'
  513.     db    cr,lf,' numerical equivalents of  \nnn  decimal'
  514.     db    ' or \Onnn  octal or \Xnnn  hexadecimal',cr,lf
  515.     db    ' or keywords  ON  or  OFF  (translation is initially off)'
  516.     db    cr,lf,'$'
  517.  
  518. takchlp    db    cr,lf,'Value 0 to 65535 for COUNT in script IF COUNT command$'
  519.  
  520. nummsg1 db    cr,lf,'?Use a number between $'
  521. nummsg2    db    ' and $'
  522. srvthlp    db    'seconds, 0-255, waiting for a transaction$'
  523. unkchhlp db    cr,lf,' Disposition of files arriving with unknown'
  524.     db    ' character sets:',cr,lf,'  Keep (default), Cancel$'
  525. winhelp    db    cr,lf,'Number of sliding window slots 1 (no windowing) to 32$'
  526. eophlp    db    ' Decimal number between 0 and 31$'
  527. ctlhlp    db    ' Decimal number between 0 and 31, 128 and 159$'
  528. cntlhlp db    cr,lf,' PREFIXED <0..31, 128..159> protectively quotes this'
  529.     db    ' control code',cr,lf
  530.     db    ' UNPREFIXED <0..31, 128..159> sends control code as-is'
  531.     db    cr,lf,' Use ALL to change all codes at once.$'
  532. sohhlp    db    ' Decimal number between 0 and 31.',cr,lf,' Special case:'
  533.     db    ' up to 126, but reduces strength of the protocol.$'
  534. dmphlp    db    ' Filename to hold screen dumps$'
  535. prnhlp    db    ' Filename for printer output (default is PRN)$'
  536. prnerr    db    cr,lf,' Cannot open that name. Using default of PRN$'
  537. erlhlp    db    ' Decimal number between 0 and 255$'
  538. pakerr    db    cr,lf,'?Choose a decimal number '
  539.     db    'from 20 to 94 (normal) or to 9024 (long)$'
  540. pakhlp    db    cr,lf,'Decimal number between 20 and 94 (normal) or '
  541.     db    '9024 (long)$'
  542. padhlp    db    cr,lf,' Decimal number between 0 and 31 or 127$'
  543. pauhlp    db    ' Decimal number between 0 and 65383 milliseconds$'
  544. quohlp    db    ' Decimal number between 33 and 126$'
  545. retryhlp db    ' Decimal number between 1 and 63$'
  546. rollhlp    db    ' Decimal number between 0 and 8000$'
  547. dblhlp    db    ' Decimal number between 0 and 255$'
  548. stophlp    db    ' Serial port stop bits, 1 (default) or 2$'
  549. luserh    db    cr,lf,'Username Password from remote Kermit (0-16 chars each)$'
  550. lpassh    db    cr,lf,'Password from remote Kermit (0-16 chars,'
  551.     db    ' spaces allowed)$'
  552. prefhlp    db    cr,lf,' single char (def is ~) or number between 33-62 or'
  553.     db    ' 96-126$'
  554. timhlp    db    ' Decimal number between 0 and 94$'
  555. delyhlp    db    ' Delay seconds before sending file (0-63)$'
  556. eschlp    db    cr,lf,'Press literal control keys (ex: Control ]) or'
  557.     db    ' enter in \nnn numerical form$'
  558. hnd1hlp    db    cr,lf,'XON (\17), XOFF (\19), CR (\13), LF (\10), BELL (\7),'
  559.     DB    ' ESC (\27), NONE (\0)'
  560.     db    cr,lf,' or "CODE" followed by decimal number$' 
  561. intoms    db    'number of seconds to wait before timeout',cr,lf,'$'
  562. loghlp    db    cr,lf
  563.     db    ' PACKETS - during file transfers  (to default file PACKET.LOG)'
  564.     db    cr,lf
  565.     db    ' SESSION - during Connect mode   (to default file SESSION.LOG)'
  566.     db    cr,lf
  567.     db    ' TRANSACTIONS - files transfers (to default file TRANSACT.LOG)'
  568.     db    cr,lf,'  followed by an optional filename for the log and'
  569.     db    ' optional',cr,lf,' '
  570. loghlp2    db    ' APPEND (default) or NEW$'
  571. carhlp    db    cr,lf,' ON or OFF. Sense modem Carrier Detect and end'
  572.     db    ' connection if it drops.$'
  573. comhlp    db    cr,lf,' Set port address, IRQ, and control UART FIFO.'
  574.     db    cr,lf,' Address of the COM1 - COM4 port (ex: COM3 \x02f8 or'
  575.     db    ' COM4 \x02e8)$'
  576. irqhlp    db    cr,lf,' IRQ of port (ex: \3)$'
  577. fifohlp db    cr,lf,' FIFO-disable or FIFO-enable or press Enter key.'
  578.     db    cr,lf,' FIFO-disable means bypass UART buffer$'
  579. debhlp    db    cr,lf,' PACKETS - during file transfers'    ; Debugging
  580.     db    cr,lf,' SESSION - during Connect mode'
  581.     db    cr,lf,' ON - both packets and session'
  582.     db    cr,lf,' OFF - turns off all debugging$'
  583. dialhlp    db    ' Phone number to dial$'
  584. dohlp    db    cr,lf,'definitions of variables (\%n), or press ENTER key$'
  585. fossilhlp db    cr,lf,' OFF to leave Fossil active (default), ON to disable'
  586.     db    ' when done with port$'
  587. sdshlp    db    cr,lf,'DISABLE or ENABLE access to selected Server commands:'
  588.     db    cr,lf
  589.     db    ' CD/CWD, DEFINE, DEL, DIR, FINISH (includes BYE & LOGOUT),'
  590.     db    ' GET, HOST,',cr,lf
  591.     db    ' KERMIT, LOGIN, PRINT, QUERY, RETRIEVE, SEND, SPACE, TYPE,'
  592.     db    ' and ALL.$'
  593.  
  594. xfchhlp    db    cr,lf,' Which character set to put on the wire during file'
  595.     db    ' transfers:',cr,lf
  596.     db    '  TRANSPARENT (regular PC codes)',cr,lf
  597.     db    '  LATIN1    (ISO 8859-1)',cr,lf
  598.     db    '  LATIN2    (ISO 8859-2)',cr,lf
  599.     db    '  HEBREW    (ISO 8859-8)',cr,lf
  600.     db    '  CYRILLIC  (ISO 8859-5)',cr,lf
  601.     db    '  JAPANESE-EUC$'
  602. xferhlp1 db    cr,lf,' OFF: disable feature, ON: enable (default), FORCE:'
  603.     db    ' forced on$'
  604. xfchhlp2 db    cr,lf,' READABLE: translate some/many characters to/from'
  605.     db    ' locally readable form (def).'
  606.     db    cr,lf,' INVERTIBLE: use codes which can be copied back to the'
  607.     db    ' host in its form.$'
  608. xferhlp3 db    cr,lf,'Automatic (Binary mode between like systems),'
  609.     db    ' manual (default)$'
  610. xfilhlp    db    'NONE, SPACE, or filler character$'
  611. xpmthlp db    'Host echo char acting as prompt, \1-\255$'
  612. xpauhlp    db    'Millisec to pause between lines, 1 - 65000$'
  613. opacehlp db    'Millisec to pause between OUTPUT bytes, 0 - 65000$'
  614. pophlp    db    'Status value to be returned  msg, nothing if no new value$'
  615. sethlp    db    cr,lf
  616.     db    '  Alarm    sec from now or HH:MM:SS  '
  617.     db    '  Local-echo        on/off           '
  618.     db    cr,lf
  619.     db    '  Attributes packets on/off          '
  620.     db    '  Mode-line         on/off'
  621.     db    cr,lf
  622.     db    '  Bell    on/off    at end of xfers  '
  623.     db    '  NetBios-name      (our local name)'
  624.     db    cr,lf
  625.     db    '  Block-check-type  checksum/CRC     '
  626.     db    '  Output pacing (ms between bytes)  '
  627.     db    cr,lf
  628.     db    '  Carrier  sense modem Carrier Detect'
  629.     db    '  Parity    even/odd/mark/space/none'
  630.     db    cr,lf
  631.     db    '  COM1 - COM4 port-address irq       '
  632.     db    '  Port (or Line)    1/2/COM1/COM2/etc'
  633.     db    cr,lf
  634.     db    '  Control prefixed/unprefixed  code  '
  635.     db    '  Printer filespec   for Connect mode'
  636.     db    cr,lf
  637.     db    '  Count   number    a loop counter   '
  638.     db    '  Prompt  string   (new Kermit prompt)'
  639.     db    cr,lf
  640.     db    '  Debug   on/off    display packets  '
  641.     db    '  Receive parameter  many things'
  642.     db    cr,lf
  643.     db    '  Default-disk                       '
  644.     db    '  Repeat Counts (on/off)             '
  645.     db    cr,lf
  646.     db    '  Delay   secs  before Sending file  '
  647.     db    '  Retry limit for packet send/receive'
  648.     db    cr,lf
  649.     db    '  Destination   Disk/Screen/Printer  '
  650.     db    '  Rollback, terminal screens'
  651.     db    cr,lf
  652.     db    '  Display quiet/reg/serial show cnts?'
  653.     db    '  Send parameter    many things'
  654.     db    cr,lf
  655.     db    '  Dump filespec     screen to disk   '
  656.     db    '  Server parameter'
  657.     db    cr,lf
  658.     db    '  Duplex            half or full     '
  659.     db      '  Speed or Baud     many speeds'    
  660.     db    cr,lf
  661.     db    '  EOF Ctrl-Z/NoCtrl-Z  ^Z ends file? '
  662.     db    '  Stop-bits         always 1'
  663.     db    cr,lf
  664.     db     '  End-of-line char  cr or whatever   '
  665.     db    '  Take Echo or Error on/off' 
  666.     db    cr,lf
  667.     db    '  Errorlevel number   for DOS Batch  '
  668.     db    '  Telnet address,mask,nameserver etc'
  669.     db    cr,lf
  670.     db      '  Escape-char  ^]   or whatever      '
  671.     db    '  Terminal type and parameters'
  672.     db    cr,lf
  673.     db    '  Exit warning (if session active)   '
  674.     db    '  Timer     on/off  time packet waiting'
  675.     db    cr,lf
  676.     db    '  File (Character-set, Type, Warning)'
  677.     db    '  Translation IN  Connect mode rcv''d char'
  678.     db    cr,lf
  679.     db    '  Flow-control  none xon/xoff rts/cts'
  680.     db    '  Transfer Character-set (on wire) '
  681.     db    cr,lf
  682.     db    '  Handshake xon/xoff/cr/lf/bell/esc..'
  683.     db    '  Transmit  parameters, for scripts'
  684.     db    cr,lf
  685.     db    '  Incomplete file   keep/discard     '
  686.     db    '  Unknown-character-set (keep/cancel)'
  687.     db    cr,lf
  688.     db    '  Input timeout, etc  (for scripts)  '
  689.     db    '  Warning   on/off  if file renamed'
  690.     db    cr,lf
  691.     db    '  Key         key-ident   definition '
  692.     db    '  Windows  number of sliding window slots'
  693.     db    '$'
  694.  
  695. ifndef    no_tcp
  696. hosthlp    db    cr,lf,'Internet name or number (ddd.ddd.ddd.ddd) of '
  697.     db    'the remote machine$'
  698. domainhlp db    cr,lf,'Name of your domain$'
  699. subnethlp db    cr,lf,'Subnetmask, decimal ddd.ddd.ddd.ddd$'
  700. addrhelp db    cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd, of this'
  701.     db    ' machine or'
  702.     db    cr,lf,' BOOTP, DHCP, RARP, or Telebit-PPP$'
  703. iphelp    db    cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd$'
  704. tcppdinthlp db    cr,lf,'Interrupt on PC for Packet Driver, \x60 to \x7f'
  705.     db    ' or use 0 for automatic search,'
  706.     db    cr,lf,' or ODI to use Novell''s ODI interface$'
  707. tcpttyhlp db    cr,lf,' Telnet Options terminal identification override '
  708.     db    'string.'
  709.     db    cr,lf,' This does NOT modify the real terminal type.'
  710.     db    ' Press ENTER to remove this',cr,lf 
  711.     db    ' override and report the real terminal type.$'
  712. tcpnlhlp db    cr,lf,' ON sends CR LF for each CR, OFF sends CR NUL,'
  713.     db    ' RAW sends just CR$'
  714. tcpmsshlp db    cr,lf,' Maximum Segment Size, 16 to 1460 bytes$'
  715. endif    ; no_tcp
  716. arrayhlp db    ' \&<char>[size]   size of 0 undefines the array$'
  717.  
  718. data1    ends
  719.  
  720. code1    segment
  721.     extrn    makebuf:far, domath:far, strlen:far, strcpy:far
  722.     extrn    prtasz:far, decout:far, strcat:far, toupr:far
  723.     extrn    isfile:far, malloc:far, dec2di:far, takrd:far
  724.     assume     cs:code1
  725. code1    ends
  726.  
  727. code    segment
  728.     extrn comnd:near, baudst:near, prompt:near, coms:near, cwdir:near
  729.     extrn lnout:near, breakcmd:near
  730.     extrn vts:near, setalrm:near, serrst:near
  731.     extrn prnopen:near, pntflsh:near
  732. ifndef    no_network
  733.     extrn setnbios:near    ; in MSXIBM, needs stub for other machines
  734. endif    ; no_network
  735.     assume    cs:code, ds:data, es:nothing
  736.  
  737. ; DO defined macro command
  738. ; DO macname variable variable   also defines variables \%1, \%2, ...\%9
  739. DOCOM    PROC    NEAR
  740.     mov    dx,offset mcctab    ; table of macro defs
  741.     xor    bx,bx            ; help is table
  742.     mov    ah,cmkey        ; get key word (macro name)
  743.     call    comnd            ; get pointer to keyword structure
  744.     jnc    docom1            ; nc = success, bx = 16 bit data
  745.     ret                ; failure
  746. DOCOM1:    mov    domacptr,bx        ; segment of definition string
  747.     mov    comand.cmquiet,0    ; permit command echoing
  748.     mov    bx,offset decbuf+2    ; point to borrowed work buffer
  749. docom1a:mov    dx,offset dohlp        ; help
  750.     mov    comand.cmblen,decbuflen ; length of analysis buffer
  751.     mov    comand.cmdonum,1    ; \number conversion allowed
  752.     mov    ah,cmword
  753.     call    comnd
  754.     jnc    docom1b
  755.     ret
  756. docom1b:mov    si,bx            ; terminating null
  757.     sub    si,ax            ; minus length
  758.     mov    [si-2],ax        ; store length in preceeding word
  759.     add    bx,2            ; leave a full word empty
  760.     mov    word ptr [bx-2],0
  761.     or    ax,ax            ; any text?
  762.     jnz    docom1a            ; nz = got text, get more
  763.     mov    ah,cmline        ; read and discard rest of line
  764.     mov    bx,offset rdbuf        ; discard here
  765.     xor    dx,dx            ; no help
  766.     call    comnd
  767.     jnc    docom2            ; nc = success
  768.     ret
  769.  
  770. docom2:    inc    taklev            ; prepare for being in Take below
  771.     call    hidemac            ; hide previous \%0..\%9 macros
  772.     dec    taklev
  773.     call    getname            ; get name of this macro to rdbuf
  774.     mov    cx,word ptr rdbuf    ; length of "\%0 plus found name"
  775.     call    dodecom            ; define macro \%0 as macro name
  776.     jc    docomx            ; c = failure
  777.     push    es
  778.     mov    ax,domacptr        ; macro definition string segment
  779.     mov    es,ax            ; string is in es:si
  780.     xor    si,si            ; point to count word
  781.     call    docnv            ; convert macro string in-place
  782.     pop    es            ; to lift top {} and do bare "," -> CR
  783.     jc    docomx            ; c = failure
  784.  
  785.     mov    max,1            ; temp for counting 1 + number args
  786.     mov    word ptr rdbuf+4,' 1'    ; number of first variable
  787. docom3:    mov    word ptr rdbuf,0    ; clear length field, install \%x name
  788.     mov    word ptr rdbuf+2,'%\'    ; start with '\%1 '
  789.     mov    word ptr rdbuf+6,0    ; clear text field
  790.     mov    tempptr,offset rdbuf+6    ; pointer to location of found word
  791.     xor    ch,ch            ; make cx = 1 - 9
  792.     mov    cl,rdbuf+4        ; cx = word # of interest, for getwrd
  793.     sub    cl,'0'            ; remove ascii bias
  794.     mov    si,offset decbuf+2    ; source = work buffer (borrowed)
  795.     call    getwrd            ; get CX-th word from work buf (1-9)
  796.     cmp    deftemp,0        ; length of word, was it found?
  797.     je    docom4            ; e = no, end variable definition part
  798.     add    deftemp,4        ; count '\%n ' in command line length
  799.     inc    max            ; one more argument
  800.     mov    cx,deftemp        ; command length for dodecom
  801.     call    dodecom            ; add keyword+def using DEF MAC below
  802.     jc    docomx            ; c = failure
  803.     inc    rdbuf+4            ; inc number of variable in '\%n '
  804.     cmp    rdbuf+4,'9'
  805.     jbe    docom3            ; do '1' through '9', if available
  806.  
  807. docom4:    call    takopen_macro        ; create the DO the macro itself
  808.     jc    docomx            ; c = failure
  809.     mov    bx,takadr        ; point to current structure
  810.     push    es
  811.     mov    es,domacptr        ; segment of macro definition string
  812.     mov    [bx].takbuf,es        ; remember in Take structure
  813.     mov    cx,es:word ptr[0]    ; length of definition string
  814.     mov    si,cx
  815.     cmp    byte ptr es:[si+2-1],CR    ; terminates in CR?
  816.     je    docom5            ; e = yes
  817.     mov    byte ptr es:[si+2],CR    ; force CR termination
  818.     ; keeps open macro until after last command has executed, for \%digit
  819.     inc    cx            ; add CR to macro length
  820.     mov    es:[0],cx        ; update image too
  821. docom5:    pop    es
  822.     mov    [bx].takcnt,cx        ; # of unread chars in buffer
  823.     mov    cx,max            ; 1 + number of arguments
  824.     mov    [bx].takargc,cx
  825.     mov    al,taklev        ; Take level now
  826.     mov    [bx].takinvoke,al    ; remember take level of this DO
  827.     clc                ; success
  828.     ret
  829.  
  830. docomx:    inc    taklev            ; simulate Take closing
  831.     call    unhidemac        ; recover hidden variables
  832.     dec    taklev
  833.     stc                ; say failure
  834.     ret
  835. DOCOM    ENDP
  836.  
  837. ; Extract CX-th word (cx = 1-9) from buffer (SI). Enter with si = source
  838. ; string and tempptr pointing at destination. Returns deftemp (count) of
  839. ; transferred characters.
  840. ; All registers preserved.
  841. getwrd    proc    near
  842.     push    si
  843.     push    di
  844.     push    es
  845.     push    cx            ; save word counter (1-9)
  846. getwr1:    mov    ax,[si-2]        ; get length of word
  847.     or    ax,ax
  848.     jz    getwr2            ; z = zero length, no word, quit
  849.     dec    cx            ; one less word
  850.     or    cx,cx
  851.     jz    getwr2            ; z = at desired word
  852.     add    si,ax            ; step to next word (<cnt><text>)
  853.     add    si,2            ; point to text
  854.     jmp    short getwr1
  855. getwr2:    mov    deftemp,ax        ; returned length of word
  856.     mov    cx,ax            ; length of word
  857.     mov    di,tempptr        ; where to store word/string
  858.     push    ds
  859.     pop    es            ; set es to data segment
  860.     cld
  861.     rep    movsb            ; copy bytes to destination
  862.     xor    al,al
  863.     stosb                ; force null terminator
  864.     pop    cx
  865.     pop    es
  866.     pop    di
  867.     pop    si
  868.     ret
  869. getwrd    endp
  870.  
  871. ; Get macro name, given the action pointer in domacptr.
  872. ; Return rdbuf as word:length that follows, then "\%0 macro-name"
  873. getname proc    near
  874.     push    bx
  875.     push    cx
  876.     push    dx
  877.     push    si
  878.     push    di
  879.     mov    dx,domacptr        ; action word to be matched
  880.     mov    bx,offset mcctab+1    ; table of macro names, skip count
  881.     mov    word ptr rdbuf,4    ; name length and space
  882.     mov    word ptr rdbuf+2,'%\'    ; define '\%0 '
  883.     mov    word ptr rdbuf+4,' 0'
  884.     mov    cl,mcctab        ; number of entries
  885.     xor    ch,ch
  886.     jcxz    getnam3            ; z = empty table
  887. getnam1:push    cx
  888.     mov    cx,[bx]            ; length of name
  889.     mov    si,bx            ; point at structure member
  890.     add    si,2            ; plus count
  891.     add    si,cx            ; plus length of name
  892.     mov    ax,[si]            ; get action word
  893.     cmp    ax,dx            ; correct action word?
  894.     jne    getnam2            ; ne = no
  895.     push    es
  896.     push    ds
  897.     pop    es
  898.     add    word ptr rdbuf,cx    ; length of macro \%0 + name
  899.     mov    di,offset rdbuf+6    ; where to store text
  900.     mov    si,bx
  901.     add    si,2            ; source of text
  902.     cld
  903.     rep    movsb            ; copy name to rdbuf+6
  904.     mov    byte ptr [di],0        ; null terminator
  905.     pop    es
  906.     pop    cx
  907.     jmp    short getnam3        ; exit
  908. getnam2:mov    ax,[bx]            ; get length of name
  909.     add    ax,4            ; plus count and word pointer
  910.     add    bx,ax            ; point to next entry
  911.     pop    cx
  912.     loop    getnam1            ; look at next entry
  913. getnam3:pop    di
  914.     pop    si
  915.     pop    dx
  916.     pop    cx
  917.     pop    bx
  918.     ret
  919. getname    endp
  920.  
  921. ; Local macro macro macro...  
  922. ; Hides existing macros of those names, if any
  923. localmac proc    near
  924.     cmp    taklev,0        ; in a take file/macro?
  925.     je    localmx            ; e = no, quit
  926.     mov    bx,offset rdbuf+2
  927.     xor    dx,dx            ; help
  928.     mov    comand.cmper,1        ; don't expand macro
  929.     mov    ah,cmword        ; get name of macro
  930.     call    comnd
  931.     jnc    localm1
  932. localmx:mov    ah,cmeol        ; get eol
  933.     call    comnd
  934.     ret
  935. localm1:mov    word ptr rdbuf,ax    ; save name length
  936.     or    ax,ax            ; empty (end of command)?
  937.     jz    localmx            ; z = yes, quit
  938.     mov    bx,offset mcctab+1    ; table of macro names, skip count
  939.     xor    ch,ch
  940.     mov    cl,mcctab        ; number of entries
  941.     jcxz    localmx            ; z = empty table
  942.  
  943. localm2:mov    ax,word ptr rdbuf    ; get user macro name length
  944.     cmp    word ptr [bx],ax    ; name length, same?
  945.     jne    localm4            ; ne = no, get next table entry
  946.     push    cx            ; compare names
  947.     push    si
  948.     push    di
  949.     mov    cx,ax            ; length of macro (either)
  950.     mov    si,offset rdbuf+2    ; user word
  951.     mov    di,bx            ; table word length
  952.     add    di,2            ; table word
  953. localm3:mov    al,[si]
  954.     mov    ah,[di]
  955.     inc    si
  956.     inc    di
  957.     call    toupr            ; upper case both
  958.     cmp    al,ah            ; same?
  959.     loope    localm3            ; e = yes
  960.     je    short localm5        ; e = fully matched
  961.     pop    di
  962.     pop    si
  963.     pop    cx
  964. localm4:mov    ax,[bx]            ; get length of name
  965.     add    ax,4            ; plus count and word pointer
  966.     add    bx,ax            ; point to next entry
  967.     loop    localm2            ; look at next table entry
  968.     jmp    localmac        ; get next macro name
  969.  
  970. localm5:pop    di
  971.     pop    si
  972.     pop    cx
  973.     call    hidewrk            ; hide macro pointed to by bx
  974.     jmp    localmac        ; get next macro name
  975. localmac endp
  976.  
  977.  
  978. ; DEFINE and ASSIGN macro commands
  979. ; Data structures comments. Macro name is stored in table mcctab as if we
  980. ; had used macro mkeyw, such as       mkeyw 'mymac',offset my_definition.
  981. ; In detail:    dw    length of name
  982. ;        db    'name'
  983. ;        dw    segment:0 of definition string
  984. ; Mcctab begins with a byte holding the number of macros in the table; one,
  985. ;  IBM, is established at assembly time. Mcctab is 10*macmax bytes long.
  986. ; Pointer mccptr holds the offset of the next free byte in mcctab.
  987. ; Definition strings are stored in individually allocated memory as
  988. ;        dw    length of definition string below
  989. ;        db    'definition string'
  990. ; A new definition is read into buffer rdbuf+2, where word rdbuf is reserved
  991. ;  to hold the length of the macro's name during intermediate processing.
  992. ; If the definition is absent then the macro is removed from the tables.
  993. ;
  994. ; ASSIGN is equivalent to DEFINE, except in the definition string substitution
  995. ; variable names are expanded to their definitions.
  996. ; DEFINE does not expand substitution variables.
  997. ; Both commands will remove a first level curly brace pair if, and only if,
  998. ; the definition begins and ends with them (trailing whitespace is allowed).
  999. ; HIDE_ASSIGN and HIDE_DEFINE are like ASSIGN and DEFINE except the
  1000. ; destination name is expanded for substitution variables.
  1001. ;
  1002. HIDE_ASSIGN    proc    near
  1003.     mov    defkind,2        ; flag command as ASSIGN, vs DEFINE
  1004.     jmp    short dodefcom        ; common code
  1005. HIDE_ASSIGN    endp
  1006. HIDE_DEFINE    proc    near
  1007.     mov    defkind,3        ; flag command as DEFINE, vs ASSIGN
  1008.     jmp    short dodefcom        ; common code
  1009. HIDE_DEFINE    endp
  1010.  
  1011. ASSIGN    PROC    NEAR
  1012.     mov    defkind,0        ; flag command as ASSIGN, vs DEFINE
  1013.     jmp    short dodefcom        ; common code
  1014. ASSIGN    ENDP
  1015.  
  1016. UNDEFINE PROC    NEAR            ; undefine variable or array
  1017.     mov    defkind,4        ; bit 4 means undefine
  1018.     jmp    short dodefcom
  1019. UNDEFINE ENDP
  1020.  
  1021. DODEF    PROC    NEAR
  1022.     mov    defkind,1        ; flag command as DEFINE, vs ASSIGN
  1023. DODEFCOM:
  1024.     test    defkind,2        ; HIDE_assign/define?
  1025.     jnz    dodef0            ; nz = yes, expand destination
  1026.     mov    comand.cmper,1        ; do not react to '\%' in macro name
  1027. dodef0:    mov    ah,cmword
  1028.     mov    bx,offset rdbuf+2    ; buffer for macro name
  1029.     mov    word ptr rdbuf,0
  1030.     mov    comand.cmarray,1    ; allow sub in [..] of \&<char> arrays
  1031.     mov    comand.cmblen,length rdbuf-2 ; length of analysis buffer
  1032.     mov    dx,offset macmsg
  1033.     call    comnd            ; get macro name
  1034.     jnc    dodef1            ; nc = success
  1035.     ret                ; failure
  1036. dodef1:    or    ax,ax            ; null entry?
  1037.     jnz    dodef2            ; nz = no
  1038.     mov    dx,offset ermes6    ; more parameters needed
  1039.     jmp    reterr
  1040.  
  1041. dodef2:    mov    bx,offset rdbuf+2    ; start of string
  1042.     cmp    word ptr [bx],'%\'    ; \%<char> substitution variable?
  1043.     jne    dodef2b            ; ne = no
  1044.     cmp    ax,2            ; count, but missing <char>?
  1045.     ja    dodef2a            ; a = no
  1046.     mov    byte ptr [bx+2],'_'    ; slip in an underscore
  1047. dodef2a:mov    ax,3            ; limit to \%<char>, one char name
  1048.  
  1049. dodef2b:test    defkind,4        ; UNDEFINE?
  1050.     jz    dodef2c            ; z = no
  1051.     add    bx,ax            ; string length
  1052.     mov    word ptr [bx],0        ; create double null for defarray
  1053.     mov    comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
  1054.     mov    ah,cmeol        ; get eol, no definition string
  1055.     call    comnd
  1056.     jnc    dodef3            ; nc = success
  1057.     ret
  1058. dodef2c:add    bx,ax            ; point to string terminator
  1059.     mov    byte ptr [bx],' '    ; replace null with space separator
  1060.     inc    bx            ; where definition will start
  1061.     mov    ax,cmdblen        ; length of rdbuf
  1062.     sub    ax,2            ; skip initial count word
  1063.     add    ax,bx            ; next byte goes to bx
  1064.     sub    ax,offset rdbuf+2    ; amount of cmd line used
  1065.     mov    comand.cmblen,ax    ; our new buffer length
  1066.     mov    al,defkind        ; get ASSIGN/DEFINE flag
  1067.     and    al,1            ; pick out source flag bit
  1068.     mov    comand.cmper,al        ; react (ASSIGN) to '\%' in definition
  1069.     mov    comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
  1070.     mov    ah,cmline        ; get a line of text
  1071.     mov    dx,offset macmsg    ; help, bx is buffer offset
  1072.     call    comnd            ; get macro definition text
  1073.     jnc    dodef3            ; nc = success
  1074.     ret                ; failure
  1075. dodef3:    mov    dx,offset rdbuf+2
  1076.     call    strlen            ; length to cx
  1077.     jmp    short dodecom
  1078. DODEF    ENDP
  1079.  
  1080. ; Make a macro table entry and allocate buffer space.
  1081. ; Enter with rdbuf+2 et seq = <macro name><spaces><arg><spaces><arg> ...
  1082. ; and CX = byte count of line, starting at rdbuf+2.
  1083. ; Word rdbuf+0 computed here as length of keyword.
  1084. ; Allocates memory based on analyzed size of command line, returns memory
  1085. ; segment in macptr and in AX. Returns carry set if failure.
  1086. DODECOM    PROC    NEAR
  1087.     cmp    word ptr rdbuf+2,'&\'    ; dealing with arrays?
  1088.     jne    dode1            ; ne = no
  1089.     call    defarray        ; yes, do it in segment code1
  1090.     ret
  1091. dode1:    push    si            ; macro name in rdbuf+2 et seq
  1092.     push    di            ; cmd line length in deftemp
  1093.     push    es
  1094.     push    ds            ; address data segment
  1095.     pop    es
  1096.     push    deftemp
  1097.     mov    deftemp,cx        ; cmd line len, cx = running counter
  1098.     mov    rdbuf,0            ; number of chars in keyword so far
  1099.                     ; uppercase the keyword, look for end
  1100.     mov    si,offset rdbuf+2    ; point at macro name itself
  1101.     xor    dx,dx            ; a counter
  1102.     cld                ; strings go forward
  1103. dode2:    lodsb                ; get a byte
  1104.     cmp    al,'a'            ; map lower case to upper
  1105.     jb    dode3
  1106.     cmp    al,'z'
  1107.     ja    dode3
  1108.     sub    al,'a'-'A'
  1109.     mov    [si-1],al        ; uppercase if necessary
  1110. dode3:    inc    dx            ; increment char count of keyword
  1111.     cmp    al,' '            ; is this the break character?
  1112.     loopne    dode2            ; no, loop thru rest of word
  1113.     jne    dode4            ; ne = did not end with break char
  1114.     dec    dx            ; yes, don't count in length
  1115. dode4:    mov    di,offset rdbuf        ; point at mac name length
  1116.     mov    [di],dx            ; insert length in rdbuf
  1117.     push    dx            ; save length around call
  1118.     call    remtab            ; remove any duplicate keyword
  1119.                     ; check for free space for keyword
  1120.     pop    ax            ; keyword text length
  1121.     add    ax,4            ; plus count and word pointer
  1122.     add    ax,mccptr        ; add to free space pointer
  1123.     cmp    ax,offset mcctab+mcclen ; enough room for name?
  1124.     jb    dode5            ; b = yes
  1125.     mov    dx,offset ermes1    ; too many macro names
  1126.     pop    deftemp
  1127.     pop    es
  1128.     pop    di
  1129.     pop    si
  1130.     jmp    reterr
  1131.                     ; should be looking one byte after
  1132.                     ; space break char between name
  1133.                     ; and definition
  1134. dode5:    mov    dx,si            ; definition string
  1135.     call    strlen            ; get new length into cx
  1136.     jcxz    dode5c            ; z = no definition, exit this routine
  1137. dode5a: mov    al,[si]            ; read a definition byte
  1138.     cmp    al,','            ; leading COMMA?
  1139.     je    dode5b            ; e = yes, from {,cmd,cmd} stuff
  1140.     cmp    al,CR            ; leading CR?
  1141.     je    dode5b            ; e = yes, skip over it
  1142.     cmp    al,' '            ; leading space?
  1143.     jne    dode6            ; ne = no, have reached def text
  1144. dode5b:    inc    si            ; inc pointer, count down qty
  1145.     loop    dode5a            ; look again (note cx > 0 check above)
  1146. dode5c:    pop    deftemp            ; exit point with no definition left
  1147.     pop    es
  1148.     pop    di
  1149.     pop    si
  1150.     clc
  1151.     ret
  1152.  
  1153. dode6:    mov    deftemp,cx        ; remember definition length here
  1154.                     ; install new keyword
  1155.     jcxz    dode10            ; z = no def (should not happen here)
  1156.     mov    ax,cx            ; memory needed
  1157.     add    ax,2+1+1        ; plus count word and CR and saftey
  1158.     call    malloc
  1159.     jc    dode12            ; c = error, not enough memory
  1160. dode7:    mov    macptr,ax        ; store new segment
  1161.     mov    es,ax            ; segment of string
  1162.     xor    di,di            ; offset of count word
  1163.     mov    cx,deftemp        ; length of definition string
  1164.     mov    ax,cx
  1165.     cld
  1166.     stosw                ; store length of string
  1167.     rep    movsb            ; copy string
  1168.     mov    bx,offset mcctab    
  1169.     mov    dx,offset rdbuf        ; count word + name string
  1170.     call    addtab
  1171. dode10:    mov    ax,macptr        ; return buffer segment to caller
  1172.     pop    deftemp
  1173.     pop    es
  1174.     pop    di
  1175.     pop    si
  1176.     clc                ; success
  1177.     ret
  1178. dode12:    pop    deftemp            ; no memory, clean stack
  1179.     pop    es
  1180.     pop    di
  1181.     pop    si
  1182.     mov    dx,offset ermes2    ; no room for definition
  1183.     mov    ah,prstr
  1184.     int    dos
  1185.     stc
  1186.     ret
  1187. DODECOM    ENDP
  1188.  
  1189. DECLARE    proc    near        ; declare array \&<char @a..z>[size]
  1190.     mov    comand.cmper,1        ; do not react to '\&' in macro name
  1191.     mov    comand.cmdonum,1    ; \number conversion allowed
  1192.     mov    comand.cmarray,1    ; allow sub in [..]
  1193.     mov    ah,cmline
  1194.     mov    bx,offset rdbuf+2    ; buffer for macro name
  1195.     mov    comand.cmblen,length rdbuf-2 ; length of analysis buffer
  1196.     mov    dx,offset arrayhlp
  1197.     call    comnd            ; get macro name
  1198.     jnc    ndecl1            ; nc = success
  1199.     ret                ; failure
  1200. ndecl1:    call    fdeclare        ; call the far version
  1201.     ret
  1202. DECLARE endp
  1203.  
  1204. ; ASK <variable or macro name> <prompt string>
  1205. ; Defines indicated variable/macro with text from user at keyboard or pipe
  1206. ; (but not from a Take/macro). Prompt string is required.
  1207. ; ASKQ does the same, but does not echo user's response.
  1208. ASKQ    PROC    NEAR
  1209.     mov    askecho,1        ; temp to flag as Quiet version
  1210.     mov    temp,0
  1211.     jmp    short ask0        ; do common code
  1212. ASKQ    ENDP
  1213.  
  1214. GETC    PROC    NEAR
  1215.     mov    askecho,1
  1216.     mov    temp,1            ; signal as getc
  1217.     jmp    short ask0        ; do common code
  1218. GETC    ENDP
  1219.  
  1220. ASK    PROC    NEAR
  1221.     mov    askecho,0        ; temp to flag as echoing version
  1222.     mov    temp,0
  1223. ask0:                    ; common code for ASK and ASKQ
  1224.     mov    bx,offset decbuf+2    ; point to work buffer
  1225.     mov    word ptr decbuf,0
  1226.     mov    dx,offset askhlp1    ; help
  1227.     mov    comand.cmper,1        ; do not expand variable name
  1228.     mov    comand.cmarray,1    ; allow sub in [..] of \&<char> arrays
  1229.     mov    ah,cmword        ; get variable name
  1230.     call    comnd
  1231.     jnc    ask1            ; nc = success
  1232.     ret                ; failure
  1233. ask1:    or    ax,ax            ; anything given?
  1234.     jnz    ask2            ; nz = yes
  1235.     mov    dx,offset ermes6    ; more parameters needed
  1236.     jmp    reterr
  1237.  
  1238. ask2:    cmp    word ptr decbuf+2,'%\'    ; \%<char> substitution variable?
  1239.     jne    ask2b            ; ne = no
  1240.     cmp    ax,2            ; but missing <char>
  1241.     ja    ask2a            ; a = no
  1242.     mov    decbuf+4,'_'        ; slip in an underscore
  1243. ask2a:    mov    ax,3            ; limit to a single char
  1244. ask2b:    mov    bx,offset decbuf+2    ; start of name
  1245.     add    bx,ax            ; plus length of variable name
  1246.     mov    word ptr [bx],0+' '    ; put space+NULL separator after name
  1247.                     ; get ASK command prompt string
  1248.     mov    bx,offset decbuf+129    ; borrowed buffer for prompt
  1249.     mov    dx,offset askhlp2
  1250.     mov    comand.cmblen,127    ; our buffer length
  1251.     sub    comand.cmblen,ax    ;  minus part used above
  1252.     mov    comand.cmdonum,1    ; \number conversion allowed
  1253.     mov    comand.cmcr,1        ; bare cr's allowed (empty prompt)
  1254.     mov    ah,cmline        ; get prompt string
  1255.     call    comnd
  1256.     jnc    ask3            ; nc = success
  1257.     ret                ; failure
  1258. ask3:    push    ax
  1259.     mov    ah,cmeol
  1260.     call    comnd
  1261.     pop    ax
  1262.     jnc    ask4
  1263.     ret
  1264.  
  1265.     or    ax,ax            ; anything given?
  1266.     jnz    ask4            ; nz = yes
  1267.     mov    dx,offset ermes6    ; more parameters needed
  1268.     jmp    reterr
  1269.  
  1270. ask4:    mov    bx,offset decbuf+129
  1271.     add    bx,ax
  1272.     mov    word ptr [bx],0020h    ; printing terminator for prompt
  1273.     mov    comand.cmdirect,1    ; say read directly from kbd/file
  1274.     mov    dx,offset decbuf+129    ; converted prompt string, asciiz
  1275.      call    prompt            ; use our prompt
  1276.     mov    bx,offset rdbuf+129    ; use this buffer for raw user input
  1277.     mov    word ptr [bx],0        ; insert terminator
  1278.     mov    dl,askecho        ; get echo/quiet flag
  1279.     mov    comand.cmquiet,dl    ; 0 if echoing
  1280.     mov    dx,offset askhlp3    ; help for user input
  1281.     mov    comand.cmdirect,1    ; say read directly from kbd/file
  1282.     cmp    temp,1            ; getc?
  1283.     jne    ask8            ; ne = no
  1284. ask5:    mov    dl,0ffh
  1285.     mov    ah,dconio        ; read console
  1286.     int    dos
  1287.     jz    ask5            ; z = nothing there
  1288.     cmp    al,3            ; Control-C?
  1289.     jne    ask6            ; ne = no
  1290.     mov    flags.cxzflg,'C'    ; return Control-C status to parser
  1291.     stc                ; return error
  1292.     ret
  1293. ask6:    or    al,al            ; scan code being returned?
  1294.     jnz    ask7            ; nz = no, accept
  1295.     mov    ah,dconio        ; read and discard second byte
  1296.     mov    dl,0ffh
  1297.     int    dos
  1298.     mov    ah,conout        ; ring the bell
  1299.     mov    dl,bell
  1300.     int    dos
  1301.     jmp    short ask5        ; else unknown, ignore
  1302.  
  1303. ask7:    xor    ah,ah            ; null terminator
  1304.     cmp    al,'('            ; function delimiters?
  1305.     je    ask7a            ; e = yes
  1306.     cmp    al,')'
  1307.     je    ask7a            ; e = yes
  1308.     cmp    al,'{'            ; string delimiters?
  1309.     je    ask7a            ; e = yes
  1310.     cmp    al,'}'
  1311.     je    ask7a            ; e = yes
  1312.     cmp    al,DEL            ; this control?
  1313.     je    ask7a            ; e = yes
  1314.     cmp    al,' '            ; senstive (controls + space)?
  1315.     ja    ask7b            ; a = no
  1316. ask7a:    mov    rdbuf+129,'\'        ; numeric form prefix
  1317.     mov    di,offset rdbuf+130
  1318.     call    dec2di            ; convert to \decimal, asciiz
  1319.     clc
  1320.     jmp    short ask9
  1321. ask7b:    mov    word ptr rdbuf+129,ax    ; byte and terminator
  1322.     clc
  1323.     jmp    short ask9        ; process byte
  1324.  
  1325. ask8:    mov    ah,cmline        ; read user's input string
  1326.     mov    comand.cmper,1        ; do not expand variable names
  1327.     mov    comand.cmdonum,1    ; \number conversion allowed
  1328.     call    comnd
  1329. ask9:    mov    comand.cmquiet,0    ; permit echoing again
  1330.     mov    comand.cmdirect,0    ; read normally again
  1331.     jnc    ask10            ; nc = success
  1332.     ret                ; Control-C, quit now
  1333. ask10:    mov    cx,ax            ; length of entry
  1334.     mov    di,offset rdbuf+2
  1335.     mov    si,offset decbuf+2
  1336.     call    strcpy
  1337.     mov    dx,di
  1338.     call    strlen
  1339.     add    di,cx
  1340.     mov    si,offset rdbuf+129
  1341.     call    strcpy
  1342.      mov    dx,offset rdbuf+2    ; command buffer beginning
  1343.     call    strlen            ; CX=len of <variable>< ><user string>
  1344.     call    DODECOM            ; define the macro/variable and exit
  1345.     ret
  1346. ASK    ENDP
  1347.  
  1348. ; GETOK <prompt>   displays prompt or default prompt, asks for affirmative
  1349. ; user reply, returns success/fail status.
  1350. getok    proc    near
  1351.     mov    bx,offset rdbuf        ; point to work buffer
  1352.     mov    dx,offset getokhlp
  1353.     mov    comand.cmblen,127    ; our buffer length
  1354.     mov    comand.cmcr,1        ; bare cr is ok
  1355.     mov    comand.cmdonum,1    ; \number conversion allowed
  1356.     mov    ah,cmline        ; get prompt string
  1357.     mov    comand.cmcr,0
  1358.     call    comnd
  1359.     jnc    getok1            ; nc = success
  1360.     ret                ; failure
  1361. getok1:    or    ax,ax            ; anything given?
  1362.     jnz    getok2            ; nz = yes
  1363.     mov    si,offset getdef    ; default prompt
  1364.     mov    di,offset rdbuf
  1365.     call    strcpy            ; paste in default prompt
  1366.  
  1367. getok2:    mov    si,offset rdbuf
  1368.     mov    dx,si
  1369.     call    strlen            ; get length to cx
  1370.     mov    bx,cx
  1371.     mov    word ptr [si+bx],0020h    ; printing terminator for prompt
  1372. getok3:    mov    dx,offset rdbuf        ; converted prompt string, asciiz
  1373.     mov    comand.cmdirect,1    ; force input from kbd/file
  1374.      call    prompt            ; use our prompt
  1375.     mov    flags.cxzflg,0        ; clear Control-C indicator
  1376.     mov    dx,offset gettab    ; use this table
  1377.     xor    bx,bx            ; table is help
  1378.     mov    comand.cmcr,1        ; null response permitted
  1379.     mov    ah,cmkey        ; read user's input word
  1380.     call    comnd
  1381.     mov    comand.cmcr,0
  1382.     mov    comand.cmdirect,0    ; end force input from kbd/file
  1383.     jnc    getok4            ; nc = success
  1384.     cmp    flags.cxzflg,'C'    ; did user type Control-C to quit?
  1385.     jne    short getok3        ; ne = no, syntax failure, reprompt
  1386.     stc                ; set carry flag again
  1387.     jmp    short getok5        ; exit failure
  1388. getok4:    push    bx
  1389.     mov    comand.cmdirect,1    ; force input from kbd/file
  1390.     mov    ah,cmeol        ; get c/r confirmation
  1391.     call    comnd
  1392.     mov    comand.cmdirect,0    ; end force input from kbd/file
  1393.     pop    bx            ; recover keyword 16 bit value
  1394. getok5:    jnc    getok6            ; nc = success
  1395.     mov    kstatus,ksgen        ; failure
  1396.     ret                ; Control-C, quit now
  1397. getok6:    mov    kstatus,bx        ; return status
  1398.     ret
  1399. getok    endp
  1400.  
  1401. ; FOR macro-name start end step {commands}
  1402. FORCMD    proc    near
  1403.     mov    kstatus,ksgen        ; general command failure
  1404.     mov    ah,cmword        ; macro name
  1405.     mov    bx,offset decbuf
  1406.     mov    dx,offset forhlp    ; help
  1407.     mov    comand.cmper,1        ; don't react to \%x variables
  1408.     call    comnd
  1409.     jnc    for1            ; nc = success
  1410. forx:    mov    ah,cmeol        ; consume and discard the rest
  1411.     call    comnd
  1412.     stc
  1413.     ret                ; failure
  1414. for1:    cmp    word ptr decbuf,'%\'    ; start of variable name?
  1415.     jne    for2            ; ne = no
  1416.     cmp    ax,3            ; only three chars in name?
  1417.     je    for3            ; e = yes, we have \%<char>
  1418. for2:    mov    dx,offset forbadname
  1419.     mov    ah,prstr
  1420.     int    dos
  1421.     jmp    short forx
  1422. for3:    mov    bx,offset decbuf+4     ; where 'start' begins
  1423.     mov    forstartptr,bx         ; remember where 'start' begins
  1424.     mov    dx,offset forhlp
  1425.     mov    ah,cmword        ; get 'start'
  1426.     call    comnd
  1427.     jc    forx            ; c = failure
  1428.     mov    bx,forstartptr        ; 'start'
  1429.     call    todigits        ; convert to string of digits
  1430.     mov    dx,offset forhlp
  1431.     jc    forx            ; c = failure
  1432.     inc    bx            ; leave null terminator intact
  1433.     mov    forendptr,bx        ; 'end' starts here
  1434.     mov    dx,offset forhlp
  1435.     mov    ah,cmword        ; get 'end'
  1436.     call    comnd
  1437.     jc    forx            ; c = failure
  1438.     mov    bx,forendptr        ; 'end' string
  1439.     call    todigits        ; convert to string of digits
  1440.     jc    forx            ; c = failure
  1441.     inc    bx            ; leave null terminator intact
  1442.     mov    forstepptr,bx        ; 'step' starts here
  1443.     mov    dx,offset forhlp
  1444.     mov    ah,cmword        ; get 'step'
  1445.     call    comnd
  1446.     jc    forx            ; c = failure
  1447.     mov    bx,forstepptr
  1448.     mov    cl,[bx]            ; get possible minus sign on step
  1449.     mov    byte ptr temp,cl    ; save for bottom of this work
  1450.     call    todigits        ; convert to string of digits
  1451.     jc    forx            ; c = failure
  1452.     inc    bx            ; leave null terminator intact
  1453.     mov    forcmdsptr,bx        ; commands start here
  1454.     mov    dx,offset forhlp
  1455.     mov    comand.cmper,1        ; don't react to \%x variables
  1456.     mov    comand.cmblen,cmdblen    ; allow long lines
  1457.     mov    comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
  1458.     mov    ah,cmline        ; get {commands}
  1459.     call    comnd
  1460.     jc    forx            ; c = failure
  1461. ; At this point decbuf looks like this:
  1462. ; <string variable name><byte null><string end><byte null>
  1463. ;  <string step><byte null><string commands><byte null>
  1464.  
  1465. for4:                    ; define variable<space><start>
  1466.     mov    si,offset decbuf    ; start of variable name
  1467.     mov    di,offset rdbuf+2
  1468.     call    strcpy            ; variable name
  1469.     mov    dx,di
  1470.     call    strlen            ; length to cx for dodecom
  1471.     add    di,cx
  1472.     mov    byte ptr [di],' '    ; space
  1473.     inc    di            ; look at next byte
  1474.     push    di            ; where number is formed
  1475.     mov    si,forstartptr
  1476.     call    strcpy            ; copy start
  1477.     mov    dx,di
  1478.     call    strlen
  1479.     add    dx,cx            ; point at terminating null
  1480.     mov    di,dx
  1481.     mov    word ptr [di],'-'    ; minus, null
  1482.     mov    si,forstepptr        ; step
  1483.     call    strcat            ; append, have (start - step)
  1484.     pop    di
  1485.  
  1486.     mov    dx,di
  1487.     mov    domath_ptr,dx
  1488.     call    strlen
  1489.     mov    domath_cnt,cx
  1490.     call    domath            ; math to dx:ax
  1491.     push    word ptr decbuf
  1492.     push     word ptr decbuf+2    ; preserve variable name \%c 
  1493.     call    lnout            ; DX:AX to DS:DI as ASCII digits
  1494.     pop    word ptr decbuf+2    ; retore variable around work
  1495.     pop    word ptr decbuf
  1496.     mov    dx,offset rdbuf+2    ; buffer for dodecom
  1497.     call    strlen            ; length to cx for dodecom
  1498.     call    dodecom            ; define macro<space>start<null>
  1499.     mov    si,offset forstr1    ; build composite command string
  1500.     mov    di,offset rdbuf+2    ; starting at rdbuf+2
  1501.     call    strcpy            ; 'forinc '
  1502.     mov    si,offset decbuf    ; 'variable'
  1503.     call    strcat
  1504.     mov    si,offset space        ; space null
  1505.     call    strcat
  1506.     mov    si,forstepptr        ; 'step'
  1507.     call    strcat
  1508.     mov    si,offset forstr2    ; cr,'if not > '
  1509.     call    strcat
  1510.     cmp    byte ptr temp,'-'    ; negative step?
  1511.     jne    for4a            ; ne = no
  1512.     mov    dx,offset rdbuf+2
  1513.     call    strlen
  1514.     add    dx,cx            ; points at trailing null
  1515.     mov    si,dx
  1516.     mov    byte ptr [si-2],'<'    ; reverse sense of test for neg step
  1517. for4a:    mov    si,offset decbuf    ; 'variable'
  1518.     call    strcat
  1519.     mov    si,offset space        ; space null
  1520.     call    strcat
  1521.     mov    si,forendptr        ; 'end'
  1522.     call    strcat
  1523.     mov    si,offset space        ; space null
  1524.     call    strcat
  1525.     mov    si,forcmdsptr        ; 'commands'
  1526.     call    strcat
  1527.  
  1528.     mov    dx,offset rdbuf+2    ; string is built at rdbuf+2
  1529.     call    strlen
  1530.     mov    ax,cx            ;
  1531.     add    ax,2+1            ; bytes needed plus ending CR
  1532.     call    malloc
  1533.     mov    es,ax            ; seg
  1534.     mov    di,2            ; start two bytes in
  1535.     mov    si,offset rdbuf+2
  1536.     push    cx
  1537.     cld
  1538.     rep    movsb            ; copy from rdbuf+2 to malloc'd area
  1539.     pop    cx
  1540.     mov    al,CR
  1541.     stosb
  1542.     inc    cx            ; count CR in macro
  1543.     call    takopen_macro        ; open a macro
  1544.     mov    bx,takadr        ; point to current macro structure
  1545.     mov    ax,es            ; segment of definition
  1546.     mov    [bx].takbuf,ax        ; segment of definition string struc
  1547.     mov    [bx].takcnt,cx        ; number of chars in definition
  1548.     mov    es:[0],cx        ; buffer usage, for rewinding
  1549.     mov    [bx].takargc,0        ; our argument count
  1550.     mov    [bx].takptr,2        ; offset to read next command char
  1551.     or    [bx].takattr,take_malloc ; free buffer when done
  1552.     or    [bx].takattr,take_while
  1553.     clc
  1554.     ret
  1555. FORCMD    endp
  1556.  
  1557. ; Perform "inc variable step" from first two command line words
  1558. _forinc proc    near
  1559.     mov    ah,cmword        ; read variable name
  1560.     mov    comand.cmper,1        ; don't expand variable names here
  1561.     mov    bx,offset rdbuf+2    ; buffer
  1562.     xor    dx,dx            ; no help
  1563.     call    comnd
  1564.     jc    forincx            ; c = failure
  1565.     
  1566.     mov    word ptr rdbuf,ax    ; save length of macro name
  1567.     mov    si,offset mcctab    ; table of macro names
  1568.     cld
  1569.     lodsb
  1570.     xor    ch,ch
  1571.     mov    cl,al            ; number of macro entries
  1572.     or    al,al
  1573.     jnz    forinc4            ; nz = have some
  1574. forincx:mov    ah,cmeol        ; kill rest of line
  1575.     mov    comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
  1576.     call    comnd
  1577.     stc
  1578.     ret
  1579.                     ; find variable
  1580. forinc4:push    cx            ; save loop counter
  1581.     lodsw                ; length of macro name to ax
  1582.     mov    cx,word ptr rdbuf    ; length of user's string
  1583.     cmp    ax,cx            ; variable name same as user spec?
  1584.     jne    forinc6            ; ne = no, no match
  1585.     push    ax
  1586.     push    si            ; save these around match test
  1587.     mov    di,offset rdbuf+2    ; user's string
  1588. forinc5:mov    ah,[di]
  1589.     inc    di
  1590.     lodsb                ; al = mac name char, ah = user char
  1591.     and    ax,not 2020h        ; clear bits (uppercase chars)
  1592.     cmp    ah,al            ; same?
  1593.     loope    forinc5            ; while equal, do more
  1594.     pop    si            ; restore regs
  1595.     pop    ax
  1596.     jne    forinc6            ; ne = no match
  1597.     pop    cx            ; remove loop counter
  1598.     jmp    short forinc7        ; e = match
  1599. forinc6:add    si,ax            ; point to next name, add name length
  1600.     add    si,2            ;  and string pointer
  1601.     pop    cx            ; recover loop counter
  1602.     loop    forinc4            ; one less macro to examine
  1603.     jmp    forincx            ; failed to locate
  1604.  
  1605. forinc7:mov    ax,[si-2]        ; get length of variable string
  1606.     add    si,ax            ; point to segment of definition
  1607.     mov    si,[si]            ; seg of definition
  1608.     push    es
  1609.     mov    es,si
  1610.     mov    cx,es:[0]        ; length of definition
  1611.     mov    di,offset rdbuf+2    ; variable name from user
  1612.     add    di,[di-2]        ; plus length of variable name
  1613.     mov    byte ptr [di],' '    ; <count><varname><space>
  1614.     inc    di
  1615.     mov    si,2            ; skip over definition count word
  1616. forinc9:mov    al,es:[si]        ; copy string to regular data segment
  1617.     mov    [di],al
  1618.     inc    si
  1619.     inc    di
  1620.     loop    forinc9
  1621.     pop    es
  1622.  
  1623.     mov    byte ptr [di],'+'
  1624.     inc    di
  1625.     push    di            ; save place after '+'
  1626.     mov    bx,di            ; optional step goes here
  1627.  
  1628.     mov    ah,cmword        ; get step size, if any
  1629.     xor    dx,dx            ; no help at this level
  1630.     call    comnd
  1631.     pop    di
  1632.     jc    forincx            ; c = fail
  1633.                     ; now convert step size, if any
  1634.     or    ax,ax            ; is length zero?
  1635.     jnz    forinc15        ; nz = no, convert number to binary
  1636.     mov    word ptr [di],'1'    ; put '1' where optional is missing
  1637.  
  1638. forinc15:
  1639.     mov    di,offset rdbuf+2    ; user's variable name
  1640.     add    di,[di-2]        ; its length
  1641.     inc    di            ; skip space separator
  1642.     push    di            ; save for place to write result
  1643.     mov    dx,di
  1644.     call    strlen            ; get string length
  1645.     mov    domath_cnt,cx
  1646.     mov    domath_ptr,dx
  1647.     call    domath            ; convert to number in dx:ax
  1648.     cmp    domath_cnt,0        ; converted whole word?
  1649.     pop    di            ; clean stack
  1650.     jne    forincx            ; ne = no, fail
  1651.                     ; step size is in ax
  1652.     or    dx,dx            ; is result negative?
  1653.     jns    forinc16        ; ns = no, positive or zero
  1654.     neg    dx            ; flip sign
  1655.     neg    ax
  1656.     sbb    dx,0
  1657.     mov    byte ptr [di],'-'    ; show minus sign
  1658.     inc    di
  1659. forinc16:call    lnout            ; binary to ascii decimal in ds:di
  1660.     mov    dx,offset rdbuf+2    ; place of <var><space><value>
  1661.     call    strlen            ; length to cx for dodecom
  1662.     call    dodecom            ; re-define variable
  1663.     clc                ; return to let rest of cmd execute
  1664.     ret                ; as an IF statement
  1665. _forinc endp
  1666.  
  1667. ; Convert numeric expression to string of digits as a replacement, asciiz.
  1668. ; Enter with BX=start of expression, AX= length of expression.
  1669. ; Returns BX=null at end of number and carry clear if success,
  1670. ; or carry set and no change if failure
  1671. todigits proc    near
  1672.     mov    domath_ptr,bx        ; source text
  1673.     mov    domath_cnt,ax        ; length
  1674.     call    domath
  1675.     jnc    todigits1        ; nc = converted value
  1676.     ret                ; fail
  1677. todigits1:
  1678.     push    di
  1679.     mov    di,bx            ; where to write
  1680.     or    dx,dx            ; is result negative?
  1681.     jns    todigits2        ; ns = no, positive or zero
  1682.     neg    dx            ; flip sign
  1683.     neg    ax
  1684.     sbb    dx,0
  1685.     mov    byte ptr [di],'-'    ; show minus sign
  1686.     inc    di
  1687. todigits2:
  1688.     call    lnout            ; convert DX:AX to ASCIIZ in DS:DI
  1689.     mov    bx,di            ; point to trailing null
  1690.     pop    di
  1691.     clc                ; success
  1692.     ret
  1693. todigits endp
  1694.  
  1695. ; Initialize macro IBM at Kermit startup time
  1696. initibm    proc    near
  1697.     mov    si,offset ibmmac    ; text of IBM macro
  1698.     mov    di,offset rdbuf+2    ; where command lines go
  1699.     call    strcpy            ; copy it there
  1700.     mov    dx,di            ; get length of command line
  1701.     call    strlen            ; set cx to length, for dodecom
  1702.     call    dodecom            ; now define the macro
  1703.     mov    rdbuf+2,0
  1704.     mov    si,offset dialmac
  1705.     mov    di,offset rdbuf+2
  1706.     call    strcpy
  1707.     mov    dx,di
  1708.     call    strlen
  1709.     inc    cx
  1710.     jmp    dodecom            ; now define the macro
  1711. initibm    endp
  1712.  
  1713. ; Open an text subsititution macro. No buffer is allocated.
  1714. takopen_sub    proc    far
  1715.     cmp    taklev,maxtak        ; room in take level?
  1716.     jb    takosub1        ; b = yes
  1717.     mov    dx,offset ermes4    ; say too many Take files
  1718.     mov    ah,prstr        ; display error message
  1719.     int    dos
  1720.     stc                ; set carry for failure
  1721.     ret
  1722.  
  1723. takosub1:push    ax
  1724.     push    bx
  1725.     mov    bx,takadr        ; previous take structure
  1726.     push    [bx].takargc        ; stash argument count
  1727.     push    [bx].takctr        ; stash COUNT
  1728.     add    takadr,size takinfo    ; pointer to new Take structure
  1729.     inc    taklev
  1730.     mov    bx,takadr        ; pointer to new Take structure
  1731.     pop    [bx].takctr        ; copy in old count
  1732.     pop    [bx].takargc        ; copy in old argc
  1733.     xor    ax,ax
  1734.     mov    [bx].takbuf,ax        ; seg of memory block
  1735.     mov    [bx].takptr,2        ; where to read first
  1736.     mov    [bx].takcnt,ax        ; unread bytes in buffer
  1737.     mov    [bx].takper,al        ; expand macros
  1738.     mov    [bx].takattr,al        ; attribute, none
  1739.     mov    [bx].taktyp,take_sub    ; kind is text substitution
  1740.     mov    [bx].takinvoke,0
  1741.     pop    bx
  1742.     pop    ax
  1743.     clc
  1744.     ret
  1745. takopen_sub    endp
  1746.  
  1747. ; Open take structure for file input. Buffer of tbufsiz is preallocated
  1748. ; and pointed to by takbuf:takptr.
  1749. takopen_file    proc    far
  1750.     call    takopen_sub        ; do substitution macro busy work
  1751.     jnc    takofil1        ; nc = success so far
  1752.     ret                ; fail
  1753. takofil1:push    bx
  1754.     mov    bx,takadr
  1755.     mov    ax,tbufsiz        ; size of buffer
  1756.     call    malloc
  1757.     jnc    takofil2        ; nc = success
  1758.     pop    bx
  1759.     ret                ; fail
  1760.  
  1761. takofil2:mov    [bx].takbuf,ax        ; seg of allocated buffer
  1762.     mov    [bx].takattr,take_malloc ; remember so takclos will free it
  1763.     mov    [bx].taktyp,take_file    ; disk file kind
  1764.     mov    [bx].takhnd,0        ; file handle
  1765.     mov    word ptr [bx].takseek,0
  1766.     mov    word ptr [bx].takseek+2,0 ; seek distance, bytes
  1767.     or    [bx].takattr,take_autocr ; need auto CR at EOF
  1768.     mov    [bx].takinvoke,0
  1769.     pop    bx
  1770.     clc
  1771.     ret
  1772. takopen_file    endp
  1773.  
  1774. ; Open an internal (macro) structure. No buffer is allocated.
  1775. ; Return carry clear for success, carry set for failure.
  1776.  
  1777. takopen_macro    proc    far
  1778.     push    ax
  1779.     push    bx
  1780.     push    cx
  1781.     push    dx
  1782.     cmp    taklev,maxtak        ; room in take level?
  1783.     jb    takoma1            ; b = yes
  1784.     mov    dx,offset ermes4    ; say too many Take files
  1785.     mov    ah,prstr        ; display error message
  1786.     int    dos
  1787.     stc                ; set carry for failure
  1788.     jmp    takoma2
  1789.  
  1790. takoma1:xor    ax,ax
  1791.     xor    cx,cx
  1792.     cmp    taklev,0        ; at top level now?
  1793.     je    takoma3            ; e = yes
  1794.     mov    bx,takadr
  1795.     mov    ax,[bx].takargc        ; get argument count
  1796.     mov    cx,[bx].takctr        ; get COUNT
  1797. takoma3:add    takadr,size takinfo    ; pointer to new Take structure
  1798.     inc    taklev
  1799.     mov    bx,takadr        ; pointer to new Take structure
  1800.     mov    [bx].takargc,ax        ; copy in old argc
  1801.     mov    [bx].takctr,cx        ; copy in old count
  1802.     xor    ax,ax
  1803.     mov    [bx].takbuf,ax        ; no segment of Take buffer
  1804.     mov    [bx].takcnt,ax        ; number of unread bytes
  1805.     mov    [bx].takptr,2        ; init pointer to definition itself
  1806.     mov    [bx].takper,al        ; expand macros
  1807.     mov    [bx].takattr,take_autocr ; need auto CR at EOF
  1808.     mov    [bx].taktyp,take_macro    ; macro
  1809.     mov    [bx].takinvoke,0
  1810.     clc                ; carry clear for success
  1811. takoma2:pop    dx
  1812.     pop    cx
  1813.     pop    bx
  1814.     pop    ax
  1815.     ret
  1816. takopen_macro endp
  1817.  
  1818. ; Close Take file. Enter at Take level to be closed.
  1819. ; Closes disk file, pops Take level.
  1820.  
  1821. TAKCLOS    PROC    FAR
  1822.     cmp    taklev,0        ; anything to close?
  1823.     jg    takclo1            ; g = yes
  1824.     ret
  1825. takclo1:push    ax
  1826.     push    bx
  1827.     push    cx
  1828.     mov    bx,takadr
  1829.     test    [bx].takattr,take_malloc ; new malloc'd buffer in takbuf?
  1830.     jz    takclo2            ; z = no
  1831.     mov    ax,[bx].takbuf
  1832.     push    es
  1833.     mov    es,ax            ; seg of separately malloc'd buffer
  1834.     mov    ah,freemem        ; free it
  1835.     int    dos
  1836.     pop    es
  1837.     and    [bx].takattr,not take_malloc ; no extra buffer to free
  1838. takclo2:mov    al,[bx].taktyp
  1839.     cmp    al,take_macro        ; macro?
  1840.     je    takclo3            ; e = yes
  1841.     cmp    al,take_file        ; disk file?
  1842.     jne    takclo6            ; ne = no, leaves sub and comand kinds
  1843.     mov    word ptr [bx].takseek,0    ; disk file
  1844.     mov    word ptr [bx].takseek+2,0 ; seek distance, bytes
  1845.     mov    bx,[bx].takhnd        ; get file handle
  1846.     mov    ah,close2        ; close file
  1847.     int    dos
  1848.     jmp    short takclo6
  1849.                     ; macros, remove argument array
  1850. takclo3:cmp    [bx].takargc,0        ; any arguments to macro?
  1851.     je    takclo5            ; e = no
  1852.     mov    word ptr settemp,3    ; remove \%0..9 macros. length word
  1853.     mov    word ptr settemp+2,'%\'    ; "\%digit"
  1854.     mov    settemp+4,'0'
  1855. takclo4:mov    di,offset settemp    ; buffer remtab reads
  1856.     call    remtab            ; remove macro
  1857.     inc    settemp+4        ; next digit
  1858.     cmp    settemp+4,'9'        ; done last?
  1859.     jbe    takclo4            ; be = no
  1860. takclo5:call    unhidemac        ; rename previous hidden macros
  1861.  
  1862. takclo6:mov    bx,takadr        ; all kinds of Take
  1863.     xor    al,al            ; get a null
  1864.     mov    [bx].taktyp,al        ; clear to avoid confusion
  1865.     mov    [bx].takper,al        ; macro expansion flag
  1866.     mov    [bx].takattr,al        ; attributes
  1867.     dec    taklev            ; pop macro Take level
  1868.     sub    takadr,size takinfo    ; get previous Take's address
  1869.     pop    cx
  1870.     pop    bx
  1871.     pop    ax
  1872.     ret
  1873. TAKCLOS    ENDP
  1874.  
  1875. ; POP/END command. Defend against command parser closing the Take/Macro at
  1876. ; the end of file. Return optional trailing number in ERRORLEVEL (errlev).
  1877. POPCMD    proc    near
  1878.     mov    oldifelse,0        ; don't permit ELSE after failed IF
  1879.     mov    ifelse,0
  1880.     mov    ah,cmword        ; get optional error value and msg
  1881.     mov    bx,offset rdbuf
  1882.     mov    dx,offset pophlp    ; help on numerical argument
  1883.     mov    comand.cmcr,1        ; bare c/r's allowed
  1884.     call    comnd
  1885.     mov    comand.cmcr,0        ; restore normal state
  1886.     jc    popcmdx            ; c = failure
  1887.     mov    ah,cmline        ; get optional error value and msg
  1888.     mov    bx,offset rdbuf+100
  1889.     mov    dx,offset pophlp    ; help on numerical argument
  1890.     mov    comand.cmcr,1        ; bare c/r's allowed
  1891.     mov    comand.cmdonum,1    ; \number conversion allowed
  1892.     call    comnd
  1893.     mov    comand.cmcr,0        ; restore normal state
  1894.     jc    popcmdx            ; c = failure
  1895.     mov    domath_ptr,offset rdbuf
  1896.     mov    domath_cnt,ax
  1897.     call    domath            ; convert to number in ax
  1898.     jc    popcmd2            ; c = not a number
  1899.     mov    errlev,al        ; return value in ERRORLEVEL
  1900.     mov    kstatus,ax        ; and in STATUS
  1901.     mov    si,offset rdbuf+100
  1902. popcmd1:lodsb                ; read a msg char
  1903.     or    al,al            ; null terminator?
  1904.     jz    popcmd2            ; z = empty string
  1905.     cmp    al,' '            ; leading white space?
  1906.     je    popcmd1            ; be = leading white space
  1907.     dec    si            ; backup to non-white char
  1908.     mov    dx,offset crlf
  1909.     mov    ah,prstr
  1910.     int    dos
  1911.     mov    dx,si            ; message
  1912.     call    prtasz
  1913. popcmd2:call    poplevel        ; do the pop
  1914. popcmdx:ret
  1915. POPCMD    endp
  1916.  
  1917. ; Common Get keyword + Get Confirm sequence. Call with dx = keyword table,
  1918. ; bx = help message offset. Returns result in BX. Modifies AX, BX.
  1919. ; Returns carry clear if sucessful else carry set. Used in many places below.
  1920. keyend    proc    near
  1921.     mov    ah,cmkey
  1922.     call    comnd
  1923.     jnc    keyend1            ; nc = success
  1924.     ret                ; failure
  1925. keyend1:push    bx            ; save returned results around call
  1926.     mov    ah,cmeol        ; get c/r confirmation
  1927.     call    comnd
  1928.     pop    bx            ; recover keyword 16 bit value
  1929.     ret                ; return with carry from comnd
  1930. keyend    endp
  1931.  
  1932. srvdsa    proc    near            ; DISABLE Server commands
  1933.     mov    dx,offset srvdetab
  1934.     mov    bx,offset sdshlp
  1935.     call    keyend
  1936.     jc    srvdsa1            ; c = failure
  1937.     cmp    apctrap,0        ; disable from APC
  1938.     jne    srvdsa1            ; ne = yes
  1939.     or    denyflg,bx        ; turn on bit (deny) for that item
  1940. srvdsa1:ret
  1941. srvdsa    endp
  1942.  
  1943. srvena    proc    near            ; ENABLE Server commands
  1944.     mov    dx,offset srvdetab    ; keyword table
  1945.     mov    bx,offset sdshlp    ; help on keywords
  1946.     call    keyend
  1947.     jc    srvena1            ; c = failure
  1948.     cmp    apctrap,0        ; disable from APC
  1949.     jne    srvena1            ; ne = yes
  1950.     not    bx            ; invert bits
  1951.     and    denyflg,bx        ; turn off (enable) selected item
  1952. srvena1:ret
  1953. srvena    endp
  1954.  
  1955. ; DIAL arg list
  1956. ; Invokes macro DIAL with args or, if not present, then macro "\0IAL"
  1957. ; defined above, with args.
  1958. dial    proc    near
  1959.     mov    kstatus,kssuc        ; assume success
  1960.     mov    word ptr decbuf,4    ; length of our name
  1961.     mov    word ptr decbuf+2,'ID'    ; prefix with "DIAL "
  1962.     mov    word ptr decbuf+4,'LA'
  1963.     call    dialcom            ; look for macro "DIAL"
  1964.     jnc    dial1            ; nc = found "DIAL"
  1965.     mov    si,offset dialmac    ; default string "__DIAL"
  1966.     mov    di,offset decbuf+2    ; destination
  1967.     push    es
  1968.     mov    ax,seg decbuf
  1969.     mov    es,ax
  1970.     mov    cx,6            ; string length
  1971.     cld
  1972.     rep    movsb            ; copy string
  1973.     pop    es
  1974.     mov    word ptr decbuf,6    ; string length
  1975.     call    dialcom            ; look for it
  1976.     jc    dialx            ; c = failed, quit
  1977. dial1:    jmp    docom1            ; DO macro with bx set for domacptr
  1978.  
  1979. dialx:    mov    kstatus,kstake        ; Take file command failure
  1980.     stc                ; fail
  1981.     ret
  1982. dial    endp
  1983.  
  1984. ; Worker for DIAL command. Find macro whose name is in offset decbuf+2
  1985. ; and whose length is in word ptr decbuf.
  1986. ; Return carry clear and macro seg in BX if success, else carry set.
  1987. dialcom    proc    near
  1988.     push    si
  1989.     push    di
  1990.     push    es
  1991.     mov    ax,ds
  1992.     mov    es,ax            ; check for existence of macro
  1993.     mov    bx,offset mcctab    ; table of macro names
  1994.     mov    cl,[bx]            ; number of names in table
  1995.     xor    ch,ch
  1996.     jcxz    dialcx            ; z = empty table, do nothing
  1997.     inc    bx            ; point to length of first name
  1998. dialc2:    mov    ax,[bx]            ; length of this name
  1999.     cmp    ax,word ptr decbuf    ; length same as desired keyword?
  2000.     jne    dialc3            ; ne = no, search again
  2001.     mov    si,bx
  2002.     add    si,2            ; point at first char of macro name
  2003.     push    cx            ; save name counter
  2004.     push    di            ; save reg
  2005.     mov    cx,word ptr decbuf    ; length of name
  2006.     mov    di,offset decbuf+2    ; point at desired macro name
  2007.     push    es            ; save reg
  2008.     push    ds
  2009.     pop    es            ; make es use data segment
  2010.     cld
  2011.     repe    cmpsb            ; match strings
  2012.     pop    es            ; need current si below
  2013.     pop    di            ; recover saved regs
  2014.     pop    cx
  2015.     jne    dialc3            ; ne = not matched
  2016.     add    bx,ax            ; length of name
  2017.     add    bx,2            ; count + name, points at word ptr
  2018.     mov    bx,[bx]            ; return word ptr in BX
  2019.     clc                ; say success
  2020.     jmp    short dialcx        ; and return
  2021.     
  2022. dialc3:    add    bx,ax            ; step to next name, add name length
  2023.     add    bx,4            ; + count and def word ptr
  2024.     loop    dialc2            ; try next name
  2025.     stc                ; say failure
  2026. dialcx:    pop    es
  2027.     pop    di
  2028.     pop    si            ; no macro
  2029.     ret
  2030.  
  2031. dialcom    endp
  2032.  
  2033. ; This is the SET command
  2034. ; Called analyzers return carry clear for success, else carry set.
  2035. SETCOM    PROC    NEAR            ; Dispatch all SET commands from here
  2036.     mov    kstatus,kssuc        ; global status, success
  2037.     mov    dx,offset settab    ; Parse a keyword from the set table
  2038.     mov    bx,offset sethlp
  2039.     mov    ah,cmkey
  2040.     call    comnd
  2041.     jc    setcom1            ; c = failure
  2042.     jmp    bx            ; execute analyzer routine
  2043. setcom1:ret
  2044. SETCOM    endp
  2045.  
  2046. SETATT    PROC    NEAR            ; Set attributes on | off
  2047.     mov    dx,offset atttab
  2048.     xor    bx,bx
  2049.     mov    ah,cmkey
  2050.     call    comnd
  2051.     jc    setatt3            ; c = failure
  2052.     mov    dx,bx            ; hold results in dx
  2053.     cmp    dl,0ffh            ; ON/OFF (all of them)?
  2054.     je    setatt1            ; e = yes
  2055.     push    dx
  2056.     mov    dx,offset ontab        ; get on/off state
  2057.     xor    bx,bx
  2058.     mov    ah,cmkey
  2059.     call    comnd
  2060.     pop    dx
  2061.     jc    setatt3            ; c = failure
  2062.     mov    dh,bl            ; store on/off state in dh
  2063. setatt1:push    dx
  2064.     mov    ah,cmeol
  2065.     call    comnd
  2066.     pop    dx
  2067.     jc    setatt3
  2068.     mov    al,flags.attflg        ; current flags
  2069.     not    dl            ; all but those affected
  2070.     and    al,dl            ; turn off affected flags
  2071.     or    dh,dh            ; off (dh = 0)?
  2072.     jz    setatt2            ; z = yes
  2073.     not    dl            ; affected flags back again as ones
  2074.     or    al,dl            ; turn on affected flags
  2075. setatt2:mov    flags.attflg,al
  2076. setatt3:ret
  2077. SETATT    ENDP
  2078.  
  2079. ; SET BAUD or SET SPEED
  2080. ; See system dependent routine BAUDST in file MSXxxx.ASM
  2081.  
  2082. ; SET BELL on or off
  2083.  
  2084. BELLST    PROC    NEAR
  2085.     mov    dx,offset ontab        ; on/off table
  2086.     xor    bx,bx            ; help
  2087.     call    keyend
  2088.     jc    bellst1            ; c = failure
  2089.     mov    flags.belflg,bl
  2090. bellst1:ret
  2091. BELLST    ENDP
  2092.  
  2093. ; SET BLOCK-CHECK
  2094.  
  2095. BLKSET    PROC    NEAR
  2096.     mov    dx,offset blktab    ; table
  2097.     xor    bx,bx            ; help, use table
  2098.     call    keyend
  2099.     jc    blkset1            ; c = failure
  2100.     mov    dtrans.chklen,bl    ; use this char as initial checksum
  2101. blkset1:ret
  2102. BLKSET    ENDP
  2103.  
  2104. ; SET CARRIER {ON, OFF}
  2105. setcar    proc    near
  2106.     mov    dx,offset ontab        ; table
  2107.     mov    bx,offset carhlp    ; help, use table
  2108.     call    keyend
  2109.     jc    setcar1            ; c = failure
  2110.     mov    flags.carrier,bl    ; value
  2111.     mov    cardet,0        ; clear carrier detect variable
  2112.     clc
  2113. setcar1:ret
  2114. setcar    endp
  2115.  
  2116. ; Set port addresses for COM1 .. COM4 at Kermit initialization time via
  2117. ; Environment. Called by command parser while doing Environment reading in
  2118. ; mssker.asm and via SET COM1 .. SET COM4.
  2119. COM1PORT proc    near
  2120.     mov    bx,0            ; offset of com1 port address
  2121.     jmp    short comport
  2122. COM1PORT endp
  2123. COM2PORT proc    near
  2124.     mov    bx,2            ; offset of com2 port address
  2125.     jmp    short comport
  2126. COM2PORT endp
  2127. COM3PORT proc    near
  2128.     mov    bx,4            ; offset of com3 port address
  2129.     jmp    short comport
  2130. COM3PORT endp
  2131.  
  2132. COM4PORT proc    near
  2133.     mov    bx,6            ; offset of com4 port address
  2134. ;;    jmp    comport
  2135. COM4PORT endp
  2136.  
  2137. COMPORT    proc    near            ; worker for above
  2138.     push    bx            ; save offset
  2139.     shr    bx,1            ; address bytes 0..3
  2140.     mov    ah,portfifo[bx]        ; save existing port values
  2141.     mov    al,portirq[bx]
  2142.     mov    temp2,ax        ; worker word
  2143.     mov    bx,offset rdbuf
  2144.     mov    dx,offset comhlp
  2145.     mov    ah,cmword        ; get port address number
  2146.     call    comnd
  2147.     jnc    compor3
  2148.     pop    bx            ; fail
  2149.     ret
  2150. compor3:mov    numerr,0        ; no error message
  2151.     mov    min,100h        ; smallest number
  2152.     mov    max,0fff0h        ; largest magnitude
  2153.     mov    numhlp,0        ; help
  2154.     call    numwd            ; parse this word
  2155.     jnc    compor4            ; nc = success, value in ax
  2156.     pop    bx
  2157.     ret
  2158. compor4:mov    temp1,ax        ; save port address
  2159.     mov    bx,offset rdbuf
  2160.     mov    dx,offset irqhlp
  2161.     mov    ah,cmword        ; read IRQ
  2162.     call    comnd
  2163.     jnc    compor5
  2164.     pop    bx
  2165.     ret
  2166. compor5:
  2167.     push    ax
  2168.     push    bx
  2169.     mov    ah,cmkey
  2170.     mov    bx,offset fifohlp    ; help
  2171.     mov    dx,offset FIFOtab    ; action table
  2172.     mov    comand.cmcr,1        ; null response permitted
  2173.     call    comnd
  2174.     jc    compor8            ; c = nothing present
  2175.     mov    byte ptr temp2+1,bl    ; save FIFO setting
  2176. compor8:pop    bx
  2177.     pop    ax
  2178.  
  2179.     push    ax
  2180.     mov    ah,cmeol        ; get command confirmation
  2181.     call    comnd
  2182.     pop    ax
  2183.     jnc    compor5a        ; nc = success
  2184.     ret
  2185. compor5a:or    ax,ax            ; anything given?
  2186.     jz    compor7            ; z = no
  2187.     mov    numhlp,0        ; help
  2188.     mov    numerr,0        ; no error message
  2189.     mov    min,2            ; smallest number
  2190.     mov    max,15            ; largest magnitude
  2191.     call    numwd            ; parse this word
  2192.     jnc    compor6            ; nc = success
  2193.     pop    bx
  2194.     ret
  2195. compor6:mov    byte ptr temp2,al    ; save IRQ
  2196. compor7:pop    bx            ; recover offset
  2197.     cmp    word ptr machnam,'BI'    ; check for "IBM-PC"
  2198.     jne    compor1            ; ne = not this name, fail
  2199.     cmp    word ptr machnam+2,'-M'
  2200.     jne    compor1
  2201.     cmp    word ptr machnam+4,'CP'
  2202.     jne    compor1
  2203.     push    es
  2204.     mov    al,flags.comflg        ; current comms port
  2205.     dec    al            ; count from 0, as per Bios
  2206.     shl    al,1            ; double to use word index of Bios
  2207.     cmp    al,bl            ; using this port now?
  2208.     jne    compor2            ; ne = no
  2209.     call    serrst            ; reset the port
  2210. compor2:mov    cx,40h            ; segment 40h
  2211.     mov    es,cx
  2212.     mov    ax,temp1        ; port address
  2213.     mov    es:[bx],ax        ; set port address
  2214.     pop    es
  2215.     shr    bl,1            ; coms port offset 0,2,4,6 to 0,1,2,3
  2216.     mov    ax,temp2        ; FIFO and IRQ
  2217.     mov    portirq[bx],al        ; IRQ
  2218.     mov    portfifo[bx],ah        ; FIFO
  2219.     clc
  2220. compor1:ret
  2221. COMPORT    endp
  2222.  
  2223. ; Set CONTROL PREFIXED <code>, CONTROL UNPREFIXED <code>, code can be ALL
  2224. cntlset    proc    near
  2225.     push    es
  2226.     mov    di,seg decbuf        ; copy protlist to work buffer decbuf
  2227.     mov    es,di
  2228.     mov    si,offset protlist
  2229.     mov    di,offset decbuf
  2230.     mov    cx,32
  2231.     cld
  2232.     rep    movsb
  2233.     pop    es
  2234.  
  2235.     mov    dx,offset cntltab    ; table
  2236.     mov    bx,offset cntlhlp    ; help
  2237.     mov    ah,cmkey
  2238.     call    comnd
  2239.     jc    cntlsetx        ; c = failure
  2240.     mov    rdbuf,bl        ; save operation value
  2241. cntlse1:mov    ah,cmword        ; get optional error value and msg
  2242.     mov    bx,offset rdbuf+1
  2243.     mov    dx,offset ctlhlp    ; help on numerical argument
  2244.     call    comnd
  2245.     jc    cntlsetx        ; c = failure
  2246.     mov    si,offset rdbuf+1    ; skip operational value in rdbuf
  2247.     or    ax,ax            ; anything given?
  2248.     jnz    cntlse2            ; nz = yes
  2249.     mov    ah,cmeol        ; confirm
  2250.     call    comnd
  2251.     jc    cntlsetx        ; c = failure
  2252.     push    es            ; copy work buffer decbuf to protlist
  2253.     mov    di,seg protlist
  2254.     mov    es,di
  2255.     mov    di,offset protlist
  2256.     mov    si,offset decbuf
  2257.     mov    cx,32
  2258.     cld
  2259.     rep    movsb
  2260.     pop    es
  2261.     clc
  2262.     ret
  2263.  
  2264. cntlse2:mov    al,[si]            ; look for ALL
  2265.     or    al,al            ; end of string?
  2266.     jz    cntlse1            ; z = yes, get more user input
  2267.     cmp    al,','            ; comma separator?
  2268.     jne    cntlse2a        ; ne = no
  2269.     inc    si            ; skip it
  2270.     jmp    short cntlse2
  2271. cntlse2a:or    al,20h            ; to lower
  2272.     cmp    al,'a'            ; a in ALL?
  2273.     je    cntlse8            ; e = got ALL
  2274. cntlse3:mov    domath_ptr,si
  2275.     mov    domath_cnt,16
  2276.     call    domath            ; convert to number in ax
  2277.     jc    cntlsety        ; c = failure
  2278.     mov    si,domath_ptr        ; next byte
  2279.     cmp    al,159            ; out of range?
  2280.     ja    cntlsety        ; a = yes
  2281.     cmp    al,128            ; in 8-bit range?
  2282.     jae    cntlse4            ; ae = yes
  2283.     cmp    al,31            ; out of range?
  2284.     ja    cntlsety        ; a = yes
  2285. cntlse4:mov    ah,rdbuf        ; protected/unprotected pointer 0/1
  2286.     mov    bl,al            ; char
  2287.     and    bl,not 80h        ; strip high bit from index
  2288.     xor    bh,bh
  2289.     or    ah,ah            ; protecting?
  2290.     jz    cntlse6            ; z = yes
  2291.     mov    ah,1            ; assume unprotecting 7-bit char
  2292.     and    al,80h            ; get high bit
  2293.     jz    cntlse5            ; z = no high bit
  2294.     mov    ah,80h            ; set high bit flag
  2295. cntlse5:or    decbuf[bx],ah        ; set unprotection bit
  2296.     jmp    cntlse2            ; get more input
  2297.  
  2298. cntlse6:mov    ah,1            ; assume protecting 7-bit char
  2299.     and    al,80h            ; get high bit
  2300.     jz    cntlse7            ; z = no high bit
  2301.     mov    ah,80h            ; set high bit flag
  2302. cntlse7:not    ah            ; invert bits
  2303.     and    decbuf[bx],ah        ; clear the unprotection bit
  2304.     jmp    cntlse2            ; get more input
  2305.  
  2306. cntlsetx:ret                ; success or failure
  2307.                     ; process ALL
  2308. cntlse8:mov    cx,32
  2309.     xor    bx,bx
  2310.     mov    al,rdbuf        ; get kind of operation
  2311.     or    al,al            ; prefix (0)?
  2312.     je    cntlse9            ; e = yes
  2313.     mov    al,81h            ; unprefix all (7 and 8 bit)
  2314. cntlse9:mov    decbuf[bx],al        ; set the state
  2315.     inc    bx
  2316.     loop    cntlse9            ; do all
  2317.     jmp    cntlse1            ; get more user input
  2318.  
  2319. cntlsety:mov    ah,cmeol        ; confirm
  2320.     call    comnd
  2321.     mov    ah,prstr
  2322.     mov    dx,offset badcntlmsg    ; say out of range
  2323.     int    dos
  2324.     stc
  2325.     ret
  2326. cntlset    endp
  2327.  
  2328. ; SET COUNTER number    for script IF COUNTER number <command>
  2329. TAKECTR    PROC    NEAR
  2330.     mov    min,0            ; get decimal char code
  2331.     mov    max,65535        ; range is 0 to 65535 decimal
  2332.     mov    numhlp,offset takchlp    ; help message
  2333.     mov    numerr,0        ; error message
  2334.     call    num0            ; convert number, return it in ax
  2335.     jc    takect2            ; c = error
  2336.     push    ax            ; save numerical code
  2337.     mov    ah,cmeol
  2338.     call    comnd            ; get a confirm
  2339.     pop    ax            ; recover ax
  2340.     jc    takect2            ; c = failure
  2341.     cmp    taklev,0        ; in a Take file?
  2342.     je    takect4            ; e = no
  2343.     push    bx
  2344.     mov    bx,takadr
  2345.     mov    [bx].takctr,ax        ; set COUNT value
  2346.     pop    bx
  2347.     clc                ; success
  2348. takect2:ret
  2349. takect4:mov    dx,offset takcerr    ; say must be in Take file
  2350.     jmp    reterr            ; display msg and return carry clear
  2351. TAKECTR    ENDP
  2352.  
  2353. ; RESET 
  2354. reset    proc    near
  2355.     mov    dx,offset resettab
  2356.     xor    bx,bx
  2357.     call    keyend
  2358.     jnc    reset1            ; nc = success
  2359.     ret                ; failure
  2360. reset1:    mov    al,bl            ; reset clock
  2361.     mov    bx,portval
  2362.     mov    starttime[bx+3],bl    ; remember in high byte
  2363.     ret
  2364. reset    endp
  2365.  
  2366. ; SET DEBUG {OFF | ON | SESSSION | PACKETS}
  2367.  
  2368. DEBST    PROC       NEAR
  2369.     mov    dx,offset debtab
  2370.     mov    bx,offset debhlp
  2371.     call    keyend
  2372.     jnc    debst1            ; nc = success
  2373.     ret                ; failure
  2374. debst1:    or    flags.debug,bl        ; set the mode, except for Off
  2375.     or    bx,bx            ; OFF?
  2376.     jnz    debst2            ; nz = no
  2377.     mov    flags.debug,bl        ; set the DEBUG flags off
  2378. debst2:    clc                ; success
  2379.     ret
  2380. DEBST    ENDP
  2381.  
  2382. ; SET DESTINATION   of incoming files
  2383.  
  2384. DESSET    PROC    NEAR
  2385.     mov    dx,offset destab
  2386.     xor    bx,bx
  2387.     call    keyend
  2388.     jc    desset1            ; c = failure
  2389.     mov    flags.destflg,bl    ; set the destination flag
  2390. desset1:ret
  2391. DESSET    ENDP
  2392.  
  2393. ; SET DEFAULT-DISK    for sending/receiving, etc
  2394. ; See cwdir in file mssker
  2395.  
  2396. ; SET DELAY seconds   Used only for SEND command in local mode
  2397. SETDELY    PROC    NEAR
  2398.     mov    min,0            ; smallest acceptable value
  2399.     mov    max,63            ; largest acceptable value
  2400.     mov    numhlp,offset delyhlp    ; help message
  2401.     mov    numerr,0        ; complaint message
  2402.     call    num0            ; parse numerical input
  2403.     jc    setdly1            ; c = error
  2404.     mov    trans.sdelay,al
  2405. setdly1:ret                ; success or failure
  2406. SETDELY    ENDP
  2407.  
  2408. ; SET DISPLAY Quiet/Regular/Serial/7-Bit/8-Bit (inverse of Set Remote on/off)
  2409. ; Accepts two keywords in one command
  2410. disply    proc    near
  2411.     mov    ah,cmkey
  2412.     mov    dx,offset distab
  2413.     mov    bx,offset dishlp
  2414.     call    comnd
  2415.     jnc    displ0            ; nc = success
  2416.     ret                ; return failure
  2417. displ0:    mov    temp1,bx        ; save parsed value
  2418.     mov    temp2,0ffffh        ; assume no second keyword
  2419.     mov    comand.cmcr,1        ; bare CR's are allowed
  2420.     mov    ah,cmkey        ; parse for second keyword
  2421.     mov    dx,offset distab
  2422.     mov    bx,offset dishlp
  2423.     call    comnd
  2424.     jc    displ1            ; no keyword
  2425.     mov    temp2,bx        ; get key value
  2426. displ1:    mov    comand.cmcr,0        ; bare CR's are not allowed
  2427.     mov    ah,cmeol
  2428.     call    comnd            ; confirm
  2429.     jnc    displ2            ; nc = success
  2430.     ret                ; failure
  2431. displ2:    mov    ax,temp1        ; examine first key value
  2432.     call    dispcom            ; do common code
  2433.     mov    ax,temp2        ; examine second key value
  2434.  
  2435. dispcom:or    ax,ax            ; check range
  2436.     jle    dispc3            ; le = not legal, ignore
  2437.     cmp    al,7            ; 7-8 bit value?
  2438.     jge    dispc2            ; ge = yes
  2439.     and    flags.remflg,not(dquiet+dregular+dserial)
  2440.     or    flags.remflg,al        ; set display mode
  2441.     clc                ; success
  2442.     ret                ; check next key value
  2443. dispc2:    cmp    al,8            ; set 8-bit wide display?
  2444.     ja    dispc3            ; a = bad value
  2445.     and    flags.remflg,not d8bit    ; assume want 7 bit mode
  2446.     cmp    al,7            ; really want 7 bit mode?
  2447.     je    dispc3            ; e = yes
  2448.     or    flags.remflg,d8bit    ; set 8 bit flag
  2449. dispc3:    clc                ; success
  2450.     ret                ; end of display common code
  2451. disply    endp
  2452.  
  2453.  
  2454. ; Set Dump filename  for saving screen images on disk.
  2455. ; Puts filename in global string dmpname
  2456. setdmp    proc    near
  2457.     mov    bx,offset rdbuf        ; work area
  2458.     mov     dx,offset dmphlp    ; help message
  2459.     mov    ah,cmword        ; allow paths
  2460.     call    comnd
  2461.     jc    setdmp2            ; c = failure
  2462.     mov    ah,cmeol
  2463.     call    comnd
  2464.     jc    setdmp2            ; c = failure
  2465.     mov    dx,offset rdbuf        ; assume we will use this text
  2466.     call    strlen            ; filename given?
  2467.     mov    si,dx            ; for strcpy
  2468.     or    cx,cx            ; length of user's filename
  2469.     jg    setdmp1            ; g = filename is given
  2470.     mov    si,offset dmpdefnam    ; no name, use default instead
  2471. setdmp1:mov    di,offset dmpname    ; copy to globally available loc
  2472.     call    strcpy
  2473.     clc
  2474. setdmp2:ret
  2475. setdmp    endp
  2476.  
  2477. ; Set DUPLEX {FULL, HALF}
  2478. setdup    proc    near
  2479.     xor    bx,bx
  2480.     mov    dx,offset duptab
  2481.     call    keyend
  2482.     jc    setdup1            ; c = failure
  2483.     mov    si,portval
  2484.     mov    [si].duplex,bl        ; set value
  2485.     mov    [si].ecoflg,0        ; turn off local echoing
  2486.     or    bl,bl            ; full duplex?
  2487.     jz    setdup1            ; z = yes
  2488.     mov    [si].floflg,0        ; no flow control for half duplex
  2489.     mov    [si].ecoflg,1        ; turn on local echoing
  2490.     call    serrst            ; reset port so opening uses above
  2491. setdup1:ret
  2492. setdup    endp
  2493.  
  2494. ; SET EOF
  2495.  
  2496. SETEOF    PROC    NEAR
  2497.     xor    bx,bx
  2498.     mov    dx,offset seoftab
  2499.     call    keyend
  2500.     jc    seteof1            ; c = failure
  2501.     mov    flags.eofcz,bl        ; set value
  2502. seteof1:ret
  2503. SETEOF    ENDP
  2504.  
  2505. ; SET End-of-Packet char (for Sent packets)
  2506. ; Archic, here for downward compatibility
  2507. EOLSET    PROC    NEAR
  2508.     mov    stflg,'S'        ; set send/receive flag to Send
  2509.     jmp    sreol            ; use Set Send/Rec routine do the work
  2510. EOLSET    ENDP
  2511.  
  2512. ; SET ERRORLEVEL number
  2513. SETERL    PROC    NEAR
  2514.     mov    numhlp,offset erlhlp    ; help
  2515.     mov    numerr,0        ; error message
  2516.     mov    min,0            ; smallest number
  2517.     mov    max,255            ; largest magnitude
  2518.     call    num0            ; parse numerical input
  2519.     jc    seterl1            ; c = error
  2520.     mov    errlev,al        ; store result
  2521.     clc
  2522. seterl1:ret
  2523. SETERL    ENDP
  2524.  
  2525. ; SET ESCAPE character.
  2526. ; Accept literal control codes and \### numbers. [jrd] 18 Oct 1987
  2527. ESCSET    PROC    NEAR
  2528.     mov    ah,cmword
  2529.     mov    bx,offset rdbuf        ; work space
  2530.     mov    dx,offset eschlp    ; help
  2531.     call    comnd
  2532.     jc    escse2            ; c = failure
  2533.     or    ax,ax            ; anything given?
  2534.     jnz    escse1            ; nz = yes
  2535.     mov    dx,offset ermes6    ; more parameters needed
  2536.     jmp    reterr
  2537. escse1:    push    ax            ; save string length
  2538.     mov    ah,cmeol        ; get a confirm
  2539.     call    comnd
  2540.     pop    ax
  2541.     jc    escse2            ; c = failure
  2542.     mov    domath_ptr,offset rdbuf
  2543.     mov    domath_cnt,ax
  2544.     call    domath            ; convert to number in ax
  2545.     cmp    ax,spc            ; is it a control code?
  2546.     jae    escse3            ; ae = no, complain
  2547.     or    ax,ax            ; non-zero too?
  2548.     jz    escse3            ; z = zero
  2549.     mov    trans.escchr,al        ; save new escape char code
  2550.     clc
  2551. escse2:    ret
  2552. escse3:    mov    dx,offset escerr
  2553.     jmp    reterr
  2554. ESCSET    ENDP
  2555.  
  2556. ; Set EXIT 
  2557. ; SET WARNING {ON, OFF}
  2558. setexitwarn proc near
  2559.     mov    dx,offset exittab    ; exit table
  2560.     xor    bx,bx
  2561.     mov    ah,cmkey
  2562.     call    comnd
  2563.     jc    setexit1
  2564.     or    bl,bl            ; warning?
  2565.     jnz    setexit1        ; nz = no
  2566.     mov    bx,offset exitwhlp    ; warning help
  2567.     mov    dx,offset ontab
  2568.     call    keyend
  2569.     jc    setexit1        ; c = failure
  2570.     mov    flags.exitwarn,bl    ; set value
  2571. setexit1:ret
  2572. setexitwarn endp
  2573.  
  2574. ; SET FILE {DISPLAY, WARNING, TYPE, CHARACTER-SET}
  2575. SETFILE    proc    near
  2576.     mov    dx,offset setfitab    ; SET FILE table
  2577.     xor    bx,bx
  2578.     mov    ah,cmkey
  2579.     call    comnd
  2580.     jc    setfiy            ; c = failure
  2581.     or    bl,bl            ; Warning?
  2582.     jnz    setfi1            ; nz = no
  2583.                     ; entry point for old SET WARNING
  2584. FILWAR:    mov    dx,offset warntab    ; warning table, on, off, no-super
  2585.     xor    bx,bx
  2586.     call    keyend
  2587.     jc    setfiy            ; c = failure
  2588.     mov    flags.flwflg,bl        ; set the filewarning flag
  2589. setfiy:    ret
  2590.  
  2591. setfi1:    cmp    bl,1            ; SET FILE CHARACTER-SET?
  2592.     jne    setfi2            ; ne = no
  2593.     mov    dx,offset setchtab    ; table of char sets
  2594.     xor    bx,bx
  2595.     call    keyend            ; get the set id
  2596.     jc    setfiy            ; c = error
  2597.     mov    flags.chrset,bx        ; save the id
  2598.     cmp    bx,866            ; setting CP866?
  2599.     jne    setfi1a            ; ne = no
  2600.     cmp    dtrans.xchset,xfr_cyrillic ; using TRANSFER of Cryillic?
  2601.     je    setfi1a            ; e = yes
  2602.     mov    dtrans.xchset,xfr_cyrillic ; force TRANSFER of Cyrillic
  2603.     mov    trans.xchset,xfr_cyrillic
  2604.     mov    ah,prstr
  2605.     mov    dx,offset setchmsg    ; show warning
  2606.     int    dos
  2607.     clc
  2608.     ret
  2609. setfi1a:cmp    bx,932            ; setting Shift-JIS?
  2610.     jne    setfi1b            ; ne = no
  2611.     mov    dtrans.xchset,xfr_japanese ; force TRANSFER of Japanese-EUC
  2612.     mov    trans.xchset,xfr_japanese
  2613.     mov    ah,prstr
  2614.     mov    dx,offset setchmsg2    ; show warning
  2615.     int    dos
  2616.     clc
  2617.     ret
  2618. setfi1b:cmp    bx,862            ; setting CP862?
  2619.     jne    setfi1c            ; ne = no
  2620.     mov    dtrans.xchset,xfr_hebiso ; force TRANSFER of Latin-Hebrew
  2621.     mov    trans.xchset,xfr_hebiso
  2622.     mov    ah,prstr
  2623.     mov    dx,offset setchmsg3    ; show warning
  2624.     int    dos
  2625. setfi1c:clc
  2626.     ret
  2627.  
  2628. setfi2:    cmp    bl,2            ; SET FILE TYPE?
  2629.     jne    setfi3            ; ne = 3
  2630.     mov    dx,offset xftyptab    ; table of types
  2631.     xor    bx,bx
  2632.     call    keyend
  2633.     jc    setfix            ; c = error
  2634.     mov    dtrans.xtype,bl        ; store transfer type
  2635.     mov    trans.xtype,bl        ; store transfer type
  2636.     ret
  2637. setfi3:    cmp    bl,3            ; SET FILE DISPLAY?
  2638.     jne    setfi4            ; ne = no
  2639.     mov    dx,offset distab2    ; table
  2640.     xor    bx,bx
  2641.     call    keyend
  2642.     jc    setfix            ; c = failure
  2643.     and    flags.remflg,not(dquiet+dregular+dserial)
  2644.     or    flags.remflg,bl        ; set display mode
  2645.     clc
  2646. setfix:    ret
  2647. setfi4:    cmp    bl,4            ; SET FILE INCOMPLETE?
  2648.     jne    setfix            ; ne = no
  2649.                     ; SET INCOMPLETE file disposition
  2650. ABFSET:    mov    dx,offset abftab
  2651.     xor    bx,bx
  2652.     call    keyend
  2653.     jc    abfset1            ; c = failure
  2654.     mov    flags.abfflg,bl        ; Set the aborted file flag
  2655. abfset1:ret
  2656. SETFILE    endp
  2657.  
  2658. ; SET FLOW-CONTROL {NONE, XONXOFF, RTS/CTS}
  2659.  
  2660. FLOSET    PROC    NEAR
  2661.     mov    dx,offset flotab
  2662.       xor    bx,bx
  2663.     call    keyend
  2664.     jc    floset3            ; c = failure
  2665.     mov    si,portval
  2666.     mov    ax,floxon        ; xon/xoff pair
  2667.     or    bx,bx            ; any flow control?
  2668.     jz    floset1            ; z = none
  2669.     test    bx,1+2            ; using xon/xoff?
  2670.     jnz    floset2            ; nz = xon/xoff
  2671.     cmp    flags.comflg,'F'
  2672.     je    floset1
  2673.     cmp    flags.comflg,4        ; UART? (RTS/CTS case)
  2674.     ja    floset4            ; a = no, error
  2675. floset1:xor    ax,ax            ; clear chars for RTS/CTS and none
  2676. floset2:mov    [si].flowc,ax        ; flow control values
  2677.     mov    [si].floflg,bl        ; flow control kind
  2678.     clc
  2679. floset3:ret
  2680. floset4:mov    dx,offset ermes7    ; error message
  2681.     jmp    reterr
  2682. FLOSET    ENDP
  2683.  
  2684. ; SET FOSSIL CLOSE-ON-DONE
  2685. FOSSET    proc    near
  2686.     mov    dx,offset fossiltab
  2687.     xor    bx,bx
  2688.     mov    ah,cmkey
  2689.     call    comnd
  2690.     jc    fossetx            ; c = failure
  2691.     mov    dx,offset ontab        ; get on/off state
  2692.     mov    bx,offset fossilhlp
  2693.     mov    ah,cmkey
  2694.     call    comnd
  2695.     jnc    fosset1
  2696.     ret                ; c = failure
  2697.  
  2698. fosset1:push    bx
  2699.     mov    ah,cmeol
  2700.     call    comnd
  2701.     pop    bx
  2702.     jc    fossetx            ; failure
  2703.     mov    fossilflag,bl        ; set flag
  2704.     clc
  2705. fossetx:ret
  2706. FOSSET    endp
  2707.  
  2708. ; SET HANDSHAKE
  2709. ; Add ability to accept general decimal code.
  2710. HNDSET    PROC    NEAR
  2711.     mov    dx,offset hndtab    ; table to scan
  2712.     mov    bx,offset hnd1hlp    ; help message
  2713.     mov    ah,cmkey
  2714.     call    comnd
  2715.     jc    hnd2            ; c = failure
  2716.     cmp    bl,0ffh            ; want a general char code?
  2717.     jne    hnd1            ; ne = no
  2718.     mov    min,0            ; get decimal char code
  2719.     mov    max,255            ; range is 0 to 255 decimal
  2720.     mov    numhlp,offset erlhlp    ; help msg
  2721.     mov    numerr,0        ; error message
  2722.     call    num0            ; convert number, return it in ax
  2723.     jc    hnd2            ; c = error
  2724.     mov    bx,ax            ; recover numerical code
  2725. hnd1:    push    bx            ; handshake type
  2726.     mov    ah,cmeol
  2727.     call    comnd            ; get a confirm
  2728.     pop    bx            ; recover bx
  2729.     jc    hnd2            ; c = failure
  2730.     mov    si,portval
  2731.     or    bl,bl            ; setting handshake off?
  2732.     jz    hnd0            ; z = yes
  2733.     mov    [si].hndflg,1        ; turn on handshaking
  2734.     mov    [si].hands,bl        ; use this char as the handshake
  2735.     clc                ; success
  2736.     ret
  2737. hnd0:    mov    [si].hndflg,bl        ; no handshaking
  2738.     clc                ; success
  2739. hnd2:    ret
  2740. HNDSET    ENDP
  2741.  
  2742. ;
  2743. ; Set Input commands (default-timeout, timeout-action, case, echo)
  2744. ; By Jim Strudevant [jrs]
  2745. INPSET    PROC    NEAR
  2746.     mov    ah,cmkey        ; key word
  2747.     mov    dx,offset inptab    ; from inputtable
  2748.     xor    bx,bx            ; no hints
  2749.     call    comnd            ; get the word
  2750.     jc    inpset1            ; c = failure
  2751.     jmp    bx            ; do the sub command
  2752. inpset1:ret
  2753. ;
  2754. ; Set Input Default-timeout in seconds
  2755. ;
  2756. inptmo:    mov    numhlp,offset intoms    ; help
  2757.     mov    numerr,0        ; error message
  2758.     mov    min,0            ; smallest number
  2759.     mov    max,-1            ; largest magnitude
  2760.     call    num0            ; parse numerical input
  2761.     jc    inptmo1            ; c = error
  2762.     mov    script.indfto,ax    ; store result
  2763. inptmo1:ret
  2764. ;
  2765. ; Set Input Timeout action (proceed or quit)
  2766. ;
  2767. inpact:    mov    dx,offset inactb    ; from this list
  2768.     xor    bx,bx            ; no hints
  2769.     call    keyend            ; get it
  2770.     jc    inpact1            ; c = failure
  2771.     mov    script.inactv,bl    ; save the action
  2772. inpact1:ret
  2773. ;
  2774. ; Set Input Echo on or off
  2775. ;
  2776. inpeco:    mov    dx,offset ontab        ; from this list
  2777.     xor    bx,bx            ; no hints
  2778.     call    keyend            ; get it
  2779.     jc    inpeco1            ; c = failure
  2780.     mov    script.inecho,bl    ; save the action
  2781. inpeco1:ret
  2782. ;
  2783. ; Set Input Case observe or ignore
  2784. ;
  2785. inpcas:    mov    dx,offset incstb    ; from this list
  2786.     xor    bx,bx            ; no hints
  2787.     call    keyend            ; get it
  2788.     jc    inpcas1            ; c = failure
  2789.     mov    script.incasv,bl    ; save the action
  2790. inpcas1:ret
  2791.  
  2792. infilt:    mov    dx,offset ontab        ; filter input, table
  2793.     xor    bx,bx
  2794.     call    keyend
  2795.     jc    infilt1
  2796.     mov    script.infilter,bl
  2797. infilt1:ret
  2798. INPSET    ENDP
  2799.  
  2800. ; Set length of script buffer for INPUT/REINPUT at Kermit initialization
  2801. ; time via Environment. Called by command parser while doing Environment
  2802. ; reading in mssker.asm. Do not call after Kermit has initialized.
  2803. SETINPBUF proc    near
  2804.     mov    scpbuflen,128        ; store default buffer length
  2805.     mov    numhlp,0        ; no help
  2806.     mov    numerr,0        ; no error message
  2807.     mov    min,2            ; smallest number (must be non-zero)
  2808.     mov    max,65535        ; largest magnitude (16 bits worth)
  2809.     call    num0            ; parse numerical input
  2810.     jc    setinpbx        ; c = error
  2811.     mov    scpbuflen,ax        ; store result
  2812.     clc
  2813. setinpbx:ret
  2814. SETINPBUF endp
  2815.  
  2816. ; SET KEY
  2817. ; Jumps to new Set Key routine
  2818. setkey    proc    near        
  2819.     cmp    stkadr,0    ; keyboard translator present?
  2820.     je    setk4        ; e = no, use this routine
  2821.     mov    bx,stkadr    ; yes, get offset of procedure
  2822.     jmp    bx        ; jump to keyboard translator
  2823. setk4:    mov    dx,offset ermes5
  2824.     jmp    reterr        ; else print error message
  2825. setkey    endp
  2826.  
  2827. ; SET LOCAL-ECHO {ON | OFF}
  2828.  
  2829. LCAL    PROC    NEAR
  2830.     mov    dx,offset ontab
  2831.     xor    bx,bx
  2832.     call    keyend
  2833.     jc    lcal1            ; c = failure
  2834.     mov    si,portval
  2835.     mov    [si].ecoflg,bl        ; Set the local echo flag
  2836. lcal1:    ret
  2837. LCAL    ENDP
  2838.  
  2839. ; LOG  {PACKETS | SESSION | TRANSACTION} filename
  2840.  
  2841. setcpt    proc    near
  2842.     mov    dx,offset logtab    ; kinds of logging
  2843.     mov    bx,offset loghlp    ; help on kind of logging
  2844.     mov    ah,cmkey        ; parse keyword
  2845.     call    comnd
  2846.     jnc    setcp20            ; nc = success
  2847.     ret                ; failure
  2848. setcp20:mov    numhlp,bx        ; save the parsed value
  2849.     mov    bx,offset rdbuf        ; holds the complete filename
  2850.     mov     dx,offset filhlp    ; ask for filename
  2851.     mov    ah,cmword        ; allow paths
  2852.     call    comnd
  2853.     jnc    setcp21            ; nc = success
  2854.     ret                ; failure
  2855. setcp21:mov    bx,offset rdbuf+100    ; optional APPEND or NEW keyword
  2856.     mov     dx,offset loghlp2    ; help with trailer keywords
  2857.     mov    ah,cmword        ; allow paths
  2858.     call    comnd
  2859.     jnc    setcp21a        ; nc = success
  2860.     ret                ; failure
  2861. setcp21a:mov    ah,cmeol
  2862.     call    comnd            ; get a confirm
  2863.     jnc    setcp22            ; nc = success
  2864.     ret                ; failure
  2865. setcp22:mov    bx,numhlp        ; recover kind of logging
  2866.     mov    dx,offset rdbuf        ; length of filename to cx
  2867.     call    strlen            ; length of given filename
  2868.     test    bl,logpkt        ; packet logging?
  2869.     jz    setcp2            ; z = no, try others
  2870.     mov    dx,offset lpktnam    ; filename
  2871.     jcxz    setcp1            ; z = no filename given
  2872.     mov    si,offset rdbuf        ; get new name
  2873.     mov    di,dx            ; destination
  2874.     call    strcpy            ; replace old name
  2875. setcp1:    cmp    ploghnd,-1        ; packet log file already open?
  2876.     je    setcp6            ; e = no, open it
  2877.     jmp    setcp16            ; say file is open already
  2878.  
  2879. setcp2:    test    bl,logses        ; session logging?
  2880.     jz    setcp4            ; z = no, try others
  2881.     mov    dx,offset lsesnam    ; use default name
  2882.     jcxz    setcp3            ; z = no filename given
  2883.     mov    si,offset rdbuf        ; get new name
  2884.     mov    di,dx            ; destination
  2885.     call    strcpy            ; replace old name
  2886. setcp3:    cmp    sloghnd,-1        ; transaction file already open?
  2887.     je    setcp6            ; e = no, open it
  2888.     jmp    setcp16            ; say file is open already
  2889.  
  2890. setcp4:    test    bl,logtrn        ; transaction logging?
  2891.     jz    setcp14            ; z = no, error
  2892.     mov    dx,offset ltranam    ; use default name
  2893.     jcxz    setcp5            ; z = no filename given
  2894.     mov    si,offset rdbuf        ; get new name
  2895.     mov    di,dx            ; destination
  2896.     call    strcpy            ; replace old name
  2897. setcp5:    cmp    tloghnd,-1        ; transaction file already open?
  2898.     je    setcp6            ; e = no, open it
  2899.     jmp    setcp16            ; say file is open already
  2900.  
  2901. setcp6:    mov    ax,dx            ; place for filename for isfile
  2902.     call    isfile            ; does file exist already?
  2903.     jc    setcp7            ; c = does not exist so use create
  2904.     test    byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
  2905.     jnz    setcp14            ; nz = no, use error exit    
  2906.     mov    ah,open2        ; open existing file
  2907.     mov    al,1+1            ;  for writing and reading
  2908.     int    dos
  2909.     jc    setcp14            ; if carry then error
  2910.     mov    bx,ax            ; file handle for seeking
  2911.     xor    cx,cx            ; high order displacement
  2912.     xor    dx,dx            ; low order part of displacement
  2913.     mov    ah,lseek        ; seek to EOF (to do appending)
  2914.     mov    al,2            ; says to EOF
  2915.     int    dos
  2916.     mov    di,word ptr rdbuf+100    ; trailing arg, get two letters
  2917.     and    di,not 2020h        ; to upper case
  2918.     cmp    di,'EN'            ; NEW?
  2919.     jne    setcp8            ; ne = no
  2920.     mov    dx,offset rdbuf        ; filename
  2921.     mov    ah,del2            ; delete to create new file below
  2922.     int    dos
  2923.  
  2924. setcp7:    test    filtst.fstat,80h    ; access problem?
  2925.     jnz    setcp14            ; nz = yes, stop here
  2926.     mov    ah,creat2        ; function is create
  2927.     mov    cx,20H            ; turn on archive bit
  2928.     int    dos            ; create the file, DOS 2.0
  2929.     jc    setcp14            ; if carry bit set then error
  2930.     mov    bx,ax            ; file handle
  2931.  
  2932. setcp8:    cmp    numhlp,logpkt        ; packet logging?
  2933.     jne    setcp9            ; ne = no
  2934.     mov    ploghnd,bx        ; save transaction log handle here
  2935.     jmp    short setcp12
  2936. setcp9:    cmp    numhlp,logses        ; session logging?
  2937.     jne    setcp10            ; ne = no
  2938.     mov    sloghnd,bx        ; save session log handle here
  2939.     jmp    short setcp12
  2940. setcp10:mov    tloghnd,bx        ; save transaction log handle here
  2941.  
  2942. setcp12:mov    ax,numhlp        ; kind of Logging
  2943.     or    flags.capflg,al        ; accumulate kinds of logging
  2944.     clc                ; success
  2945.     ret
  2946.  
  2947. setcp14:mov    dx,offset errcap    ; give error message
  2948.     jmp    reterr            ; and display it
  2949.  
  2950. setcp16:mov    ah,prstr        ; file already open
  2951.     mov    dx,offset erropn
  2952.     int    dos
  2953.     clc                ; return success
  2954.     ret
  2955. setcpt    endp
  2956.  
  2957. ; SET MODE LINE
  2958.  
  2959. MODL    PROC    NEAR
  2960.     mov    dx,offset ontab        ; parse an on or off
  2961.     xor    bx,bx            ; no special help
  2962.     call    keyend
  2963.     jc    modl1            ; c = failure
  2964.     mov    flags.modflg,bl        ; set flag appropriately
  2965. modl1:    ret
  2966. MODL    ENDP
  2967.  
  2968. ; SET OUTPUT commands
  2969. setoutput proc    near
  2970.     mov    dx,offset outputtab    ; OUTPUT command table
  2971.     xor    bx,bx            ; no special help
  2972.     mov    ah,cmkey
  2973.     call    comnd
  2974.     jc    setout1            ; c = failure
  2975.     jmp    short setopace
  2976. setout1:ret    
  2977. setoutput endp
  2978.  
  2979. ; Set OUTPUT Pacing <number millisec between chars>
  2980. setopace proc    near
  2981.     mov    numhlp,offset opacehlp    ; help
  2982.     mov    numerr,0        ; no error message
  2983.     mov    min,0            ; smallest number
  2984.     mov    max,65535        ; largest magnitude (16 bits worth)
  2985.     call    num0            ; parse numerical input
  2986.     jc    setopac1        ; c = error
  2987.     mov    outpace,ax        ; store result
  2988.     clc
  2989. setopac1:ret
  2990. setopace endp
  2991.  
  2992. ; Set Macro Error
  2993. setmacerr proc    near
  2994.     mov    dx,offset macrotab    ; keyword
  2995.     xor    bx,bx
  2996.     mov    ah,cmkey
  2997.     call    comnd
  2998.     jnc    setmacer1
  2999.     ret                ; failure
  3000. setmacer1:
  3001.     push    bx            ; save first keyword ident
  3002.     mov    dx,offset ontab        ; on/off table
  3003.     xor    bx,bx
  3004.     call    keyend
  3005.     pop    ax            ; first keyword ident
  3006.     jnc    setmacer2        ; nc = success
  3007.     ret
  3008. setmacer2:or    al,al            ; "error" (0)?
  3009.     jz    setmacer3        ; z = yes
  3010.     mov    macroerror,bl        ; set error action flag
  3011. setmacer3:clc
  3012.     ret
  3013. setmacerr endp
  3014.  
  3015. ; SET MODEM text    creates macro named _MODEM
  3016. setmodem proc    near
  3017.     mov    word ptr rdbuf+2,'m_'    ; macro name "_modem"
  3018.     mov    word ptr rdbuf+4,'do'
  3019.     mov    word ptr rdbuf+6,'me'
  3020.     mov    rdbuf+8,' '        ; separator
  3021.     mov    bx,offset rdbuf+9
  3022.     mov    ax,length rdbuf-9    ; usable length of rdbuf
  3023.     add    ax,offset rdbuf        ; ax = amount of buffer used
  3024.     mov    comand.cmblen,ax    ; our new buffer length
  3025.     mov    comand.cmdonum,1    ; \number conversion allowed
  3026.     mov    ah,cmline        ; get a line of text
  3027.     mov    dx,offset askhlp3    ; help, bx is buffer offset
  3028.     push    bx            ; save starting offset
  3029.     call    comnd            ; get macro definition text
  3030.     pop    bx
  3031.     jnc    setmod1            ; nc = success
  3032.     ret                ; failure
  3033. setmod1:mov    cx,bx
  3034.     sub    cx,offset rdbuf+2    ; length of command line
  3035.     jmp    dodecom
  3036. setmodem endp
  3037.  
  3038. ; SET PARITY
  3039.  
  3040. SETPAR    PROC    NEAR
  3041.     mov    dx,offset partab    ; parity table
  3042.     xor    bx,bx
  3043.     mov    ah,cmkey
  3044.     call    comnd
  3045.     jnc    setp1            ; nc = success
  3046.     ret
  3047. setp1:    mov    si,portval        ; port structure
  3048.     mov    bh,[si].parflg        ; current parity setting
  3049.     or    bh,bl            ; merge hardware parity bits
  3050.     mov    byte ptr temp,bh    ; save results around calls
  3051.     test    bl,PARHARDWARE        ; using hardware parity?
  3052.     jz    setpt3            ; z = no
  3053.     mov    dx,offset parhwtab    ; hardware parity table
  3054.     xor    bx,bx
  3055.     mov    ah,cmkey
  3056.     call    comnd
  3057.     jnc    setpt2
  3058.     ret
  3059. setpt2:    cmp    flags.comflg,'4'    ; physical serial port?
  3060.     jbe    setpt3            ; be = yes
  3061.     mov    dx,offset ermes8    ; say can't use Hardware on non-UART
  3062.     jmp    reterr
  3063.  
  3064. setpt3:    mov    ah,cmeol
  3065.     push    bx
  3066.     call    comnd
  3067.     pop    bx
  3068.     jnc    setpt4
  3069.     ret
  3070. setpt4:    mov    si,portval        ; port structure
  3071.     mov    [si].parflg,bl        ; store the parity flag
  3072.     test    byte ptr temp,PARHARDWARE ; used hardware before or now?
  3073.     jz    setpt5            ; z = no
  3074.     call    serrst            ; reset port for hardware reinit
  3075. setpt5:    clc
  3076.     ret
  3077. SETPAR    ENDP
  3078.  
  3079. ; Set Print filename  for writing material to printers.
  3080. ; Puts filename in global string prnname
  3081. setprn    proc    near
  3082.     mov    bx,offset rdbuf        ; work area
  3083.     mov     dx,offset prnhlp    ; help message
  3084.     mov    ah,cmword        ; allow paths
  3085.     call    comnd
  3086.     jc    setprn3            ; c = failure
  3087.     mov    ah,cmeol
  3088.     call    comnd
  3089.     jc    setprn3            ; c = failure
  3090.     mov    dx,offset rdbuf        ; assume we will use this text
  3091.     call    strlen            ; filename given?
  3092.     mov    si,dx            ; for strcpy
  3093.     or    cx,cx            ; length of user's filename
  3094.     jg    setprn1            ; g = filename is given
  3095.     mov    si,offset prndefnam    ; no name, use default instead
  3096. setprn1:mov    di,offset prnname    ; copy to globally available loc
  3097.     call    strcpy
  3098.     cmp    prnhand,0        ; handle already in use?
  3099.     jle    setprn2            ; le = no
  3100.     call    pntflsh            ; flush current buffer
  3101.     mov    bx,prnhand        ; close the file now
  3102.     cmp    bx,4            ; don't close DOS PRN
  3103.     je    setprn2            ; e = already available
  3104.     mov    ah,close2
  3105.     int    dos
  3106. setprn2:call    prnopen            ; open printer now, may set carry
  3107.     jnc    setprn3            ; nc = success
  3108.     mov    ah,prstr
  3109.     push    ds
  3110.     mov    dx,seg prnerr
  3111.     mov    ds,dx
  3112.     mov    dx,offset prnerr    ; say can't open the file
  3113.     int    dos
  3114.     pop    ds
  3115.     mov    si,offset prndefnam    ; use default name as fallback
  3116.     mov    di,offset prnname    ; copy to globally available loc
  3117.     call    strcpy
  3118.     mov    prnhand,4        ; declare handle to be DOS PRN
  3119. setprn3:ret
  3120. setprn    endp
  3121.  
  3122. ; SET PROMPT  Allow user to change the "Kermit-MS>" prompt
  3123. ; {string} and \fchar(number) notation permitted to represent special chars.
  3124. ; String will be made asciiz
  3125.  
  3126. PROMSET    PROC    NEAR
  3127.     mov    ah,cmline
  3128.     mov    bx,offset rdbuf        ; read the prompt string
  3129.     mov    dx,offset prmmsg
  3130.     mov    comand.cmblen,length promptbuf -1 ; buffer length
  3131.     mov    comand.cmper,1        ; do not allow variable substitutions
  3132.     call    comnd
  3133.     jc    prom2            ; c = failure
  3134.     or    ax,ax            ; prompt string?
  3135.     jnz    prom0            ; nz = yes
  3136.     mov    ax,offset kerm        ; no, restore default prompt
  3137.     jmp    short prom1
  3138. prom0:    mov    si,offset rdbuf        ; source = new prompt string
  3139.     mov    di,offset promptbuf    ; destination
  3140.     call    strcpy            ; copy string to final buffer
  3141.     mov    bx,ax            ; get byte count
  3142.     mov    promptbuf[bx],0        ; insert null terminator
  3143.     mov    ax,offset promptbuf
  3144. prom1:    mov    prmptr,ax        ; remember prompt buffer (old/new)
  3145.     clc                ; success
  3146. prom2:    ret
  3147. PROMSET    ENDP
  3148.  
  3149. ; SET SERVER {LOGIN username password | TIMEOUT}
  3150.  
  3151. SETSRV    PROC    NEAR
  3152.     mov    dx,offset srvtab    ; set server table
  3153.     xor    bx,bx            ; use table for help
  3154.     mov    ah,cmkey        ; get keyword
  3155.     call    comnd
  3156.     jnc    setsrv1            ; c = success
  3157.     ret
  3158. setsrv1:cmp    apctrap,0        ; disable from APC?
  3159.     jne    setsrvx            ; ne = yes
  3160.     cmp    bl,1            ; Login?
  3161.     jne    setsrv2            ; ne = no
  3162.     test    flags.remflg,dserver    ; acting as a server now?
  3163.     jz    setsrv3            ; z = no
  3164.     stc                ; fail
  3165.     ret
  3166. setsrv3:mov    bx,offset rdbuf        ; where to store local username
  3167.     mov    dx,offset luserh    ; help
  3168.     mov    comand.cmblen,16    ; buffer length
  3169.     mov    ah,cmword        ; get username
  3170.     call    comnd
  3171.     jc    setsrvx
  3172.     mov    bx,offset rdbuf+30    ; where to store local password
  3173.     mov    dx,offset lpassh    ; help
  3174.     mov    comand.cmblen,16    ; buffer length
  3175.     mov    comand.cmdonum,1    ; \number conversion allowed
  3176.     mov    ah,cmline        ; get password, allow spaces
  3177.     call    comnd
  3178.     jc    setsrvx
  3179.     mov    si,offset rdbuf        ; only now do we transfer to the
  3180.     mov    di,offset luser        ; active buffers
  3181.     call    strcpy
  3182.     mov    si,offset rdbuf+30
  3183.     mov    di,offset lpass
  3184.     call    strcpy
  3185.     clc
  3186.     ret
  3187.  
  3188. setsrv2:mov    min,0            ; Timeout, smallest acceptable value
  3189.     mov    max,255            ; largest acceptable value, one byte
  3190.     mov    numhlp,offset srvthlp    ; help message
  3191.     mov    numerr,0        ; complaint message
  3192.     call    num0            ; parse numerical input
  3193.     jc    setsrvx            ; c = error
  3194.     mov    srvtmo,al        ; store timeout value
  3195.     clc                ; success
  3196. setsrvx:ret
  3197.     
  3198. SETSRV    ENDP
  3199.  
  3200. ; Set REPEAT COUNTS {ON, OFF}
  3201. repset    proc    near
  3202.     mov    dx,offset setrep    ; repeat table
  3203.     xor    bx,bx
  3204.     mov    ah,cmkey
  3205.     call    comnd
  3206.     jnc    repset1
  3207.     ret
  3208. repset1:or    bx,bx            ; which item (counts, prefix)
  3209.     jnz    repset4            ; nz = prefix
  3210.     mov    dx,offset ontab        ; on/off table
  3211.     xor    bx,bx            ; use table for help
  3212.     call    keyend
  3213.     jnc    repset2            ; nc = success
  3214.     ret
  3215. repset2:mov    dtrans.rptqenable,bl    ; repeat quote char enable/disable
  3216.     ret
  3217. repset4:mov    ah,cmword        ; get a character
  3218.     mov    bx,offset rdbuf
  3219.     mov    rdbuf,defrptq        ; default repeat prefix char
  3220.     mov    dx,offset prefhlp
  3221.     call    comnd
  3222.     jc    repset5            ; c = fail
  3223.     push    ax
  3224.     mov    ah,cmeol
  3225.     call    comnd
  3226.     pop    ax
  3227.     jc    repset5            ; c = fail
  3228.     mov    domath_ptr,offset rdbuf
  3229.     mov    domath_cnt,ax
  3230.     mov    domath_msg,1        ; no complaints
  3231.     call    domath            ; convert numerics
  3232.     jc    repset6
  3233.     mov    rdbuf,al
  3234. repset6:mov    al,rdbuf        ; get char
  3235.     call    prechk            ; check range
  3236.     jc    repset5            ; c = failed
  3237.     mov    dtrans.rptq,al        ; set prefix
  3238. repset5:ret
  3239. repset    endp
  3240.  
  3241. ; Check if prefix in AL is in the proper range: 33-62, 96-126. 
  3242. ; Return carry clear if in range, else return carry set.
  3243. prechk    proc    near
  3244.     cmp    al,33
  3245.     jb    prechk2            ; b = out of range
  3246.     cmp    al,62
  3247.     jbe    prechk1            ; be = in range 33-62
  3248.     cmp    al,96
  3249.     jb    prechk2            ; b = out of range
  3250.     cmp    al,126
  3251.     ja    prechk2            ; a = out of range 96-126
  3252. prechk1:clc                ; carry clear for in range
  3253.     ret
  3254. prechk2:stc                ; carry set for out of range
  3255.     ret
  3256. prechk    endp
  3257. ; SET RETRY value. Changes the packet retry limit.
  3258.  
  3259. RETRYSET PROC    NEAR
  3260.     mov    min,1            ; smallest acceptable value
  3261.     mov    max,63            ; largest acceptable value
  3262.     mov    numhlp,offset retryhlp    ; help message
  3263.     mov    numerr,0        ; complaint message
  3264.     call    num0            ; parse numerical input
  3265.     jc    retrys1            ; c = error
  3266.     mov    maxtry,al
  3267. retrys1:ret
  3268. RETRYSET ENDP
  3269.  
  3270. ; Set number of screens in terminal emulator rollback buffer at Kermit
  3271. ; initialization time via Environment. Called by command parser while doing
  3272. ; Environment reading in mssker.asm. Do not call after Kermit has initialized.
  3273. SETROLLB proc    near
  3274.     mov    numhlp,offset rollhlp    ; help
  3275.     mov    numerr,0        ; no error message
  3276.     mov    min,0            ; smallest number
  3277.     mov    max,8000        ; largest magnitude
  3278.     call    num0            ; parse numerical input
  3279.     jc    setrol1            ; c = error
  3280.     mov    npages,ax        ; store result
  3281.     clc
  3282. setrol1:ret
  3283. SETROLLB endp
  3284.  
  3285. ; Set width of rollback screens in terminal emulator rollback buffer at Kermit
  3286. ; initialization time via Environment. Called by command parser while doing
  3287. ; Environment reading in mssker.asm. Do not call after Kermit has initialized.
  3288. SETWIDTH proc    near
  3289.     mov    rollwidth,80        ; default width of rolled screen
  3290.     mov    numhlp,0        ; no help
  3291.     mov    numerr,0        ; no error message
  3292.     mov    min,80            ; smallest number
  3293.     mov    max,207            ; largest magnitude (16 bits worth)
  3294.     call    num0            ; parse numerical input
  3295.     jc    setwid1            ; c = error
  3296.     mov    rollwidth,ax        ; store result
  3297.     clc
  3298. setwid1:ret
  3299. SETWIDTH endp
  3300.  
  3301. ; SET TAKE ECHO or TAKE ERROR on or off
  3302.  
  3303. TAKSET    PROC    NEAR
  3304.     mov    dx,offset taketab    ; Parse a keyword
  3305.     xor    bx,bx            ; no specific help
  3306.     mov    ah,cmkey
  3307.     call    comnd
  3308.     jnc    takset1
  3309.     ret                ; failure
  3310. takset1:push    bx            ; save command indicator
  3311.     mov    dx,offset ontab
  3312.     xor    bx,bx
  3313.     call    keyend
  3314.     pop    ax            ; recover command indicator
  3315.     jnc    takset2
  3316.     ret                ; failure
  3317. takset2:or    al,al            ; Take Echo command?
  3318.     jnz    takset3            ; nz = no
  3319.     mov    flags.takflg,bl
  3320.     clc
  3321.     ret
  3322. takset3:mov    takeerror,bl        ; Take Error command
  3323.     clc
  3324.     ret
  3325. TAKSET    ENDP
  3326.  
  3327. ; SET TIMER     on or off during file transfer
  3328.  
  3329. TIMSET    PROC    NEAR
  3330.     mov    dx,offset ontab
  3331.     xor    bx,bx
  3332.     call    keyend
  3333.     jc    timset1            ; c = failure
  3334.     mov    flags.timflg,bl
  3335. timset1:ret
  3336. TIMSET    ENDP
  3337.  
  3338. ; SET WINDOW number of windows
  3339. WINSET    PROC    NEAR
  3340.     mov    min,1            ; smallest acceptable value
  3341.     mov    max,maxwind        ; largest acceptable value
  3342.     mov    numhlp,offset winhelp    ; help message
  3343.     mov    numerr,0        ; complaint message
  3344.     call    num0            ; parse numerical input
  3345.     jc    winse5            ; c = error
  3346.     mov    dtrans.windo,al        ; store default window size
  3347.     mov    trans.windo,al        ; and in active variable for makebuf
  3348.     clc                ; success
  3349. winse5:    ret
  3350. WINSET    ENDP
  3351.  
  3352. ; SET SEND parameters
  3353.  
  3354. SENDSET    PROC    NEAR
  3355.     mov    stflg,'S'        ; Setting SEND parameter 
  3356.     mov    dx,offset stsrtb    ; Parse a keyword
  3357.     xor    bx,bx            ; no specific help
  3358.     mov    ah,cmkey
  3359.     call    comnd
  3360.     jc    sendset1        ; c = failure
  3361.     jmp    bx            ; do the action routine
  3362. sendset1:ret
  3363. SENDSET    ENDP
  3364.  
  3365. ; SET RECEIVE parameters
  3366.  
  3367. recset:    mov    stflg,'R'        ; Setting RECEIVE paramter
  3368.     mov    dx,offset stsrtb    ; Parse a keyword
  3369.     xor    bx,bx            ; no specific help
  3370.     mov    ah,cmkey
  3371.     call    comnd
  3372.     jc    recset1            ; c = failure
  3373.     jmp    bx            ; do the action routine
  3374. recset1:ret
  3375.  
  3376. remset    proc    near            ; Set REMOTE ON/OFF
  3377.     mov    dx,offset ontab
  3378.     mov    bx,offset remhlp
  3379.     call    keyend
  3380.     jc    remset2            ; c = failure
  3381.     and    flags.remflg,not (dquiet+dserial+dregular) ; no display bits
  3382.     or    bl,bl            ; want off state? (same as regular)
  3383.     jz    remset1            ; z = yes
  3384.     or    flags.remflg,dquiet    ; else on = quiet display
  3385.     clc
  3386.     ret
  3387. remset1:or    flags.remflg,dregular    ; off = regular display
  3388.     clc
  3389. remset2:ret
  3390. remset    endp
  3391.  
  3392.  
  3393. ; SET Send and Receive End-of-Packet char
  3394.  
  3395. sreol    PROC    NEAR
  3396.     mov    min,0            ; lowest acceptable value
  3397.     mov    max,1FH            ; largest acceptable value
  3398.     mov    numhlp,offset eophlp    ; help message
  3399.     mov    numerr,0        ; error message address
  3400.     call    num0            ; get numerical input
  3401.     jc    sreol3            ; c = error
  3402.     cmp    stflg,'S'        ; setting SEND paramter?
  3403.     je    sreol1
  3404.     mov    trans.reol,al
  3405.     jmp    short sreol2
  3406. sreol1:    mov    dtrans.seol,al
  3407. sreol2:    mov    ah,dtrans.seol
  3408.     mov    trans.seol,ah
  3409.     clc
  3410. sreol3:    ret
  3411. sreol    ENDP
  3412.  
  3413.  
  3414. ; SET SEND and RECEIVE start-of-header
  3415.  
  3416. srsoh:    mov    min,0
  3417.     mov    max,7eh            ; allow printables (control=normal)
  3418.     mov    numhlp,offset sohhlp    ; reuse help message
  3419.     mov    numerr,0        ; error message
  3420.     call    num0        ; Common routine for parsing numerical input
  3421.     jc    srsoh2            ; c = error
  3422.     cmp    stflg,'S'        ; setting SEND paramter?
  3423.     je    srsoh1
  3424.     mov    trans.rsoh,al        ; set Receive soh
  3425.     clc                ; success
  3426.     ret
  3427. srsoh1:    mov    trans.ssoh,al        ; set Send soh
  3428.     clc                ; success
  3429.     ret
  3430. srsoh2:    ret
  3431.  
  3432. ; SET Send Double-char
  3433.  
  3434. srdbl    PROC    NEAR
  3435.     mov    min,0            ; lowest acceptable value
  3436.     mov    max,0ffh        ; largest acceptable value
  3437.     mov    numhlp,offset dblhlp    ; help
  3438.     mov    numerr,0        ; error message address
  3439.     call    num0            ; get numerical input
  3440.     jc    sreol3            ; c = error
  3441.     cmp    stflg,'R'        ; setting Receive paramter?
  3442.     je    srdbl1            ; e = yes, no action
  3443.     mov    trans.sdbl,al        ; store character to be doubled
  3444.     mov    dtrans.sdbl,al
  3445.     clc
  3446. srdbl1:    ret
  3447. srdbl    ENDP
  3448.  
  3449. ; SET Receive Ignore-char
  3450.  
  3451. srign    PROC    NEAR
  3452.     mov    min,0            ; lowest acceptable value
  3453.     mov    max,0ffh        ; largest acceptable value
  3454.     mov    numhlp,offset dblhlp    ; reuse help
  3455.     mov    numerr,0        ; error message address
  3456.     call    num0            ; get numerical input
  3457.     jc    srign1            ; c = error
  3458.     cmp    stflg,'S'        ; setting SEND paramter?
  3459.     je    srign1            ; e = yes, no action
  3460.     mov    trans.rign,al        ; store character to be ignored
  3461.     mov    dtrans.rign,al
  3462.     clc
  3463. srign1:    ret
  3464. srign    ENDP
  3465.  
  3466. ; SET SEND and    RECEIVE TIMEOUT
  3467.  
  3468. srtim:    mov    min,0
  3469.     mov    max,94
  3470.     mov    numhlp,offset timhlp    ; Reuse help message
  3471.     mov    numerr,0        ; error message
  3472.     call    num0        ; Common routine for parsing numerical input
  3473.     jc    srtim3            ; c = error
  3474.     cmp    stflg,'S'        ; Setting SEND paramter?
  3475.     je    srtim1
  3476.     mov    trans.rtime,al
  3477.     jmp    short srtim2
  3478. srtim1:    mov    dtrans.stime,al
  3479. srtim2:    mov    ah,dtrans.stime
  3480.     mov    trans.stime,ah
  3481.     clc
  3482. srtim3:    ret
  3483.  
  3484. ; SET SEND and RECEIVE PACKET LENGTH
  3485. ; dtrans items are real, trans items are just for SHOW information
  3486.  
  3487. srpack:    mov    min,20
  3488.     mov    max,9024
  3489.     mov    numhlp,offset pakhlp    ; help
  3490.     mov    numerr,offset pakerr    ; error message
  3491.     call    num0
  3492.     jnc    srpaks0            ; nc = success
  3493.     ret                ; failure
  3494. srpaks0:cmp    stflg,'S'        ; setting send value?
  3495.     jne    srpakr            ; ne = receive
  3496.     mov    dtrans.slong,ax        ; set send max value
  3497.     mov    trans.slong,ax        ; store current active length
  3498.     mov    dtrans.spsiz,dspsiz    ; set regular 94 byte default
  3499.     mov    trans.spsiz,dspsiz    ; ditto
  3500.     cmp    ax,dspsiz        ; longer than regular packet?
  3501.     jae    srpaks1            ; ae = yes
  3502.     mov    dtrans.spsiz,al        ; shrink regular packet size too
  3503.     mov    trans.spsiz,al        ; shrink regular packet size too
  3504. srpaks1:clc                ; success
  3505.     ret
  3506.  
  3507. srpakr:    mov    dtrans.rlong,ax        ; set receive max value
  3508.     mov    trans.rlong,ax        ; store active length
  3509.     mov    dtrans.rpsiz,drpsiz    ; set regular to default 94 bytes
  3510.     mov    trans.rpsiz,drpsiz
  3511.     mov    trans.rpsiz,drpsiz
  3512.     cmp    ax,drpsiz        ; longer than a regular packet?
  3513.     jae    srpakr1            ; ae = yes
  3514.     mov    dtrans.rpsiz,al        ; shrink regular packet size too
  3515.     mov    trans.rpsiz,al
  3516. srpakr1:clc                ; success
  3517.     ret
  3518.  
  3519.  
  3520. ; SET SEND and RECEIVE number of padding characters
  3521.  
  3522. srnpd:    mov    min,0
  3523.     mov    max,94
  3524.     mov    numhlp,offset timhlp    ; reuse help message
  3525.     mov    numerr,0        ; error message
  3526.     call    num0            ; Parse numerical input
  3527.     jc    srnpd3            ; c = error
  3528.     cmp    stflg,'S'        ; Setting SEND paramter?
  3529.     je    srnpd1            ; e = yes
  3530.     mov    trans.rpad,al        ; set Receive padding
  3531.     jmp    short srnpd2
  3532. srnpd1:    mov    dtrans.spad,al        ; set default Send padding
  3533. srnpd2:    mov    al,dtrans.spad
  3534.     mov    trans.spad,al        ; update active array for I and S pkts
  3535.     clc
  3536. srnpd3:    ret
  3537.  
  3538. ; SET SEND and RECEIVE padding character
  3539.  
  3540. srpad:    mov    min,0
  3541.     mov    max,127
  3542.     mov    numhlp,offset padhlp
  3543.     mov    numerr,offset padhlp
  3544.     call    num0            ; parse numerical input
  3545.     jc    srpad4            ; c = error
  3546.     cmp    ah,127            ; this is allowed
  3547.     je    srpad1
  3548.     cmp    ah,32
  3549.     jb    srpad1            ; between 0 and 31 is OK too
  3550.     mov    ah,prstr
  3551.     mov    dx,offset padhlp
  3552.     int    dos
  3553. srpad1:    cmp    stflg,'S'        ; Send?
  3554.     je    srpad2            ; e = yes, else Receive
  3555.     mov    trans.rpadch,al        ; store receive pad char
  3556.     jmp    short srpad3
  3557. srpad2:    mov    dtrans.spadch,al    ; store Send pad char
  3558. srpad3:    mov    ah,dtrans.spadch
  3559.     mov    trans.spadch,ah      ; update active array for I and S pkts
  3560.     clc                ; success
  3561. srpad4:    ret
  3562.  
  3563. ; SET SEND and    RECEIVE control character prefix
  3564.  
  3565. srquo:    mov    min,33
  3566.     mov    max,126
  3567.     mov    numhlp,offset quohlp    ; help message
  3568.     mov    numerr,0        ; error message
  3569.     call    num0            ; Parse numerical input
  3570.     jc    srquo3            ; c = error
  3571.     cmp    stflg,'S'        ; Setting outgoing quote char?
  3572.     je    srquo1            ; e = yes
  3573.     mov    trans.rquote,al        ; set Receive quote char
  3574.     jmp    short srquo2
  3575. srquo1:    mov    dtrans.squote,al    ; set Send quote char
  3576. srquo2:    clc
  3577. srquo3:    ret
  3578.  
  3579. ; SET SEND Pause number    of milliseconds
  3580.  
  3581. srpaus:    mov    min,0
  3582.     mov    max,65383
  3583.     mov    numhlp,offset pauhlp    ; help
  3584.     mov    numerr,0
  3585.     call    num0            ; Parse numerical input
  3586.     pushf                ; save carry for error state
  3587.     cmp    stflg,'S'        ; Setting SEND paramter?
  3588.     je    srpau0
  3589.     popf
  3590.     mov    dx,offset ermes5    ; "Not implemented" msg
  3591.     jmp    reterr            ; print error message
  3592. srpau0:    popf
  3593.     jc    srpau1            ; c = error
  3594.     mov    spause,ax        ; store value
  3595. srpau1:    ret
  3596.  
  3597. ; SET RECEIVE REMOTE-PATH {enable, disable}
  3598. srpath    proc    near
  3599.     mov    dx,offset ontab
  3600.     mov    bx,offset rspathhlp
  3601.     call    keyend
  3602.     jc    srpath1
  3603.     cmp    stflg,'R'        ; Setting RECEIVE paramter?
  3604.     jne    srpath1            ; ne = no
  3605.     mov    rcvpathflg,bl        ; update receive flag
  3606.     clc
  3607.     ret
  3608. srpath1:mov    sndpathflg,bl        ; update send flag
  3609.     clc
  3610. srpath2:ret
  3611. srpath    endp
  3612.  
  3613. ; Set stop-bits
  3614. stopbit    proc    near
  3615.     mov    min,1
  3616.     mov    max,2
  3617.     mov    numhlp,offset stophlp    ; help
  3618.     mov    numerr,0
  3619.     call    num0            ; Parse numerical input
  3620.     jnc    stopbit1
  3621.     ret                ; c = failure
  3622. stopbit1:mov    bx,portval
  3623.     mov    [bx].stopbits,al    ; stop bits
  3624.     clc
  3625.     ret    
  3626. stopbit    endp
  3627.  
  3628. ; SET TCP/IP address nnn.nnn.nnn.nnn
  3629. ; SET TCP/IP subnetmask nnn.nnn.nnn.nnn
  3630. ; SET TCP/IP gateway nnn.nnn.nnn.nnn
  3631. ; SET TCP/IP primary-nameserver nnn.nnn.nnn.nnn
  3632. ; SET TCP/IP secondary-nameserver nnn.nnn.nnn.nnn
  3633. ; SET TCP/IP domain string
  3634.  
  3635. ifndef    no_tcp
  3636. tcpipset proc    near
  3637.     mov    ah,cmkey        ; get keyword
  3638.     mov    dx,offset tcptable    ; table
  3639.     xor    bx,bx            ; help
  3640.     call    comnd
  3641.     jnc    tcpse1
  3642.     ret
  3643. tcpse1:    mov    word ptr rdbuf,bx    ; keyword index
  3644.     mov    comand.cmblen,17    ; length of user's buffer
  3645.     cmp    bx,1            ; local address?
  3646.     jne    tcpse1a            ; ne = no
  3647.     mov    dx,offset addrhelp    ; address help
  3648.     jmp    short tcpse4
  3649. tcpse1a:cmp    bx,2            ; domain name?
  3650.     jne    tcpse2            ; ne = no
  3651.     mov    dx,offset domainhlp    ; domain help
  3652.     mov    comand.cmblen,32    ; length of user's buffer
  3653.     jmp    short tcpse4
  3654. tcpse2:    cmp    bx,3            ; subnet mask?
  3655.     jne    tcpse3            ; ne = no
  3656.     mov    dx,offset subnethlp
  3657.     jmp    short tcpse4
  3658. tcpse3:    cmp    bx,7            ; Host?
  3659.     jne    tcpse3a            ; ne = no
  3660.     mov    dx,offset hosthlp
  3661.     mov    comand.cmblen,60    ; length of user's buffer
  3662.     jmp    short tcpse4
  3663. tcpse3a:cmp    bx,9            ; PD interrupt?
  3664.     jne    tcpse3b            ; ne = no
  3665.     mov    dx,offset tcppdinthlp
  3666.     jmp    short tcpse4
  3667. tcpse3b:cmp    bx,10            ; term type?
  3668.     jne    tcpse3c            ; ne = no
  3669.     mov    dx,offset tcpttyhlp
  3670.     mov    comand.cmblen,32    ; length of user's buffer
  3671.     jmp    short tcpse4
  3672. tcpse3c:cmp    bx,11            ; newline mode?
  3673.     jne    tcpse3d            ; ne = no
  3674.     jmp    tcpse13
  3675. tcpse3d:cmp    bx,12            ; debug mode?
  3676.     jne    tcpse3e            ; ne = no
  3677.     jmp    tcpse14
  3678. tcpse3e:cmp    bx,13            ; binary/nvt mode?
  3679.     jne    tcpse3f            ; ne = no
  3680.     jmp    tcpse15
  3681. tcpse3f:cmp    bx,14            ; MSS?
  3682.     jne    tcpse3g            ; ne = no
  3683.     jmp    tcpse16
  3684.  
  3685. tcpse3g:mov    dx,offset iphelp    ; Internet number help
  3686. tcpse4:    mov    ah,cmword        ; get a string
  3687.     mov    bx,offset rdbuf+2    ; work buffer
  3688.     call    comnd
  3689.     jnc    tcpse5
  3690.     ret
  3691. tcpse5:    push    ax            ; save string length in ax
  3692.     mov    ah,cmeol
  3693.     call    comnd
  3694.     pop    ax
  3695.     jnc    tcpse6
  3696.     ret
  3697. tcpse6:    mov    si,offset rdbuf+2    ; user's string
  3698.     mov    bx,word ptr rdbuf    ; comand kind
  3699.     cmp    bx,2            ; domain?
  3700.     jne    tcpse8            ; ne = no
  3701.     mov    di,offset tcpdomain
  3702.     cmp    ax,32            ; exceeded 32 chars?
  3703.     jbe    tcpse7            ; be = no
  3704.     mov    ah,prstr
  3705.     mov    dx,offset domainbad    ; compain
  3706.     int    dos
  3707.     stc
  3708.     ret
  3709. tcpse7:    cmp    ax,32            ; address oversized?
  3710.     jbe    tcpse9            ; be = no
  3711.     mov    ah,prstr
  3712.     mov    dx,offset addressbad    ; say bad address
  3713.     int    dos
  3714.     stc
  3715.     ret
  3716. tcpse8:    mov    di,offset tcpaddress
  3717.     cmp    bx,1            ; local address?
  3718.     je    tcpse9            ; e = yes
  3719.     mov    di,offset tcpsubnet
  3720.     cmp    bx,3            ; subnet?
  3721.     je    tcpse9            ; e = yes
  3722.     mov    di,offset tcpgateway
  3723.     cmp    bx,4            ; gateway?
  3724.     je    tcpse9
  3725.     mov    di,offset tcpprimens
  3726.     cmp    bx,5            ; primary-nameserver?
  3727.     je    tcpse9
  3728.     mov    di,offset tcpsecondns    ; secondary-nameserer
  3729.     cmp    bx,6
  3730.     je    tcpse9
  3731.     mov    di,offset tcphost    ; host name or number
  3732.     cmp    bx,7
  3733.     je    tcpse9
  3734.     mov    di,offset tcpbcast    ; broadcast
  3735. tcpse9:    cmp    bx,9            ; port or other?
  3736.     jae    tcpse10            ; ae = yes
  3737.     call    strcpy
  3738.     clc
  3739.     ret
  3740. tcpse10:cmp    bx,9            ; PD interrupt?
  3741.     jne    tcpse12            ; ne = no
  3742.     mov    si,offset rdbuf+2
  3743. tcpse11:mov    ax,word ptr [si]
  3744.     and    ax,not 2020h        ; to upper case
  3745.     cmp    ax,'DO'            ; ODI?
  3746.     je    tcpse11a        ; e = yes, use "DO"
  3747.     push    bx
  3748.     mov    domath_ptr,si
  3749.     mov    domath_cnt,16
  3750.     call    domath            ; convert to number in ax
  3751.     pop    bx
  3752. tcpse11a:mov    tcppdint,ax
  3753.     clc
  3754.     ret
  3755. tcpse12:cmp    bx,10            ; term-type string?
  3756.     jne    tcpse13            ; ne = no
  3757.     mov    si,offset rdbuf+2
  3758.     mov    di,offset tcpttbuf    ; copy string to holding place
  3759.     call    strcpy
  3760.     clc
  3761.     ret
  3762. tcpse13:cmp    bx,11            ; newline mode?
  3763.     jne    tcpse14            ; ne = no
  3764.     mov    dx,offset newlinetab    ; newline table
  3765.     mov    bx,offset tcpnlhlp    ; help
  3766.     call    keyend
  3767.     jc    tcpse20            ; fail
  3768.     mov    tcpnewline,bl        ; set mode
  3769.     clc
  3770.     ret
  3771. tcpse14:cmp    bx,12            ; debug mode?
  3772.     jne    tcpse15            ; ne = no
  3773.     mov    dx,offset ontab        ; on/off table
  3774.     xor    bx,bx            ; help
  3775.     call    keyend
  3776.     jc    tcpse20            ; fail
  3777.     mov    tcpdebug,bl        ; set mode
  3778.     clc
  3779.     ret
  3780. tcpse15:cmp    bx,13            ; binary/nvt mode?
  3781.     jne    tcpse16            ; ne = no
  3782.     mov    dx,offset tcpmodetab    ; mode table
  3783.     xor    bx,bx            ; help
  3784.     call    keyend
  3785.     jc    tcpse20
  3786.     mov    tcpmode,bl        ; set mode
  3787.     clc
  3788.     ret
  3789. tcpse16:cmp    bx,14            ; MSS?
  3790.     jne    tcpse20            ; ne = no
  3791.     mov    numhlp,offset tcpmsshlp    ; help
  3792.     mov    min,16            ; get decimal value
  3793.     mov    max,1460        ; range is 16 to 1460 decimal
  3794.     mov    numerr,0        ; error message
  3795.     call    num0            ; convert number, return it in ax
  3796.     jc    tcpse20            ; c = error
  3797.     mov    tcpmss,ax        ; MSS
  3798.     clc
  3799.     ret
  3800. tcpse20:stc                ; fail
  3801.     ret
  3802. tcpipset endp
  3803. endif    ; no_tcp
  3804.  
  3805. ; SET TRANSFER  CHARACTER-SET {Latin1, Shift-JIS, Transparent}
  3806. ; SET TRANSFER  TRANSLATION {Readable, Invertible}
  3807. ; SET TRANSFER  MODE {Automatic, Manual}
  3808. sxfer    proc    near
  3809.     mov    dx,offset xfertab    ; table of TRANSFER keywords
  3810.     xor    bx,bx
  3811.     mov    ah,cmkey        ; get next keyword
  3812.     call    comnd
  3813.     jc    sxfer1            ; c = error
  3814.     or    bl,bl            ; Character-set?
  3815.     jnz    sxfer2            ; nz = no
  3816.     mov    dx,offset xfchtab    ; Character-set table
  3817.     mov    bx,offset xfchhlp    ; help text
  3818.     call    keyend
  3819.     jc    sxfer1            ; c = error
  3820.     mov    dtrans.xchset,bl    ; store transfer char set ident
  3821.     mov    trans.xchset,bl        ; store transfer char set ident
  3822.     cmp    bl,xfr_cyrillic        ; Cyrillic?
  3823.     jne    sxfer9            ; ne = no
  3824.     mov    ax,flags.chrset        ; get current file character set
  3825.     mov    flags.chrset,866    ; force CP866
  3826.     cmp    ax,866            ; was CP866/LATIN5 File Character set?
  3827.     je    sxfer8            ; e = yes
  3828.     mov    dx,offset xfchbad    ; show warning message
  3829.     mov    ah,prstr
  3830.     int    dos
  3831. sxfer8:    clc
  3832. sxfer1:    ret
  3833. sxfer9:    cmp    bl,xfr_japanese        ; Japanese-EUC?
  3834.     jne    sxfer10            ; ne = no
  3835.     mov    ax,flags.chrset        ; get current file character set
  3836.     mov    flags.chrset,932    ; force Shift-JIS
  3837.     cmp    ax,932            ; was Shift-JIS File Character set?
  3838.     je    sxfer8            ; e = yes
  3839.     mov    dx,offset xfchbad2    ; show warning message
  3840.     mov    ah,prstr
  3841.     int    dos
  3842.     clc
  3843.     ret
  3844. sxfer10:cmp    bl,xfr_hebiso        ; Hebrew-ISO?
  3845.     jne    sxfer8            ; ne = no
  3846.     mov    ax,flags.chrset        ; get current file character set
  3847.     mov    flags.chrset,862    ; force CP 862
  3848.     cmp    ax,862            ; was CP862 the File Character set?
  3849.     je    sxfer8            ; e = yes
  3850.     mov    dx,offset xfchbad3    ; show warning message
  3851.     mov    ah,prstr
  3852.     int    dos
  3853.     clc
  3854.     ret
  3855.  
  3856. sxfer2:    cmp    bx,1            ; LOCKING-SHIFT?
  3857.     jne    sxfer3            ; ne = no
  3858.     mov    dx,offset xfertab1    ; off, on, forced table
  3859.     mov    bx,offset xferhlp1
  3860.     call    keyend
  3861.     jc    sxfer1
  3862.     mov    dtrans.lshift,bl    ; save state
  3863.     mov    trans.lshift,bl
  3864.     clc
  3865.     ret
  3866. sxfer3:    cmp    bx,2            ; Translation table?
  3867.     jne    sxfer4            ; ne = no
  3868.     mov    dx,offset xfertab2    ; TRANSLATION table
  3869.     mov    bx,offset xfchhlp2    ; help text
  3870.     call    keyend
  3871.     jc    sxfer1            ; c = error
  3872.     mov    dtrans.xchri,bl        ; store readable/invertible flag
  3873.     mov    trans.xchri,bl
  3874.     clc
  3875.     ret
  3876. sxfer4:    mov    dx,offset xfertab3    ; MODE table
  3877.     mov    bx,offset xferhlp3    ; help text
  3878.     call    keyend
  3879.     jc    sxfer1            ; c = error
  3880.     mov    dtrans.xmode,bl        ; store file transfer mode sensing
  3881.     mov    trans.xmode,bl
  3882.     clc
  3883.     ret
  3884. sxfer    endp
  3885.  
  3886. ; SET TRANSLATION           Connect mode translate characters
  3887. ; SET TRANSLATION INPUT {Original-byte New-byte | ON | OFF}
  3888. ; SET TRANSLATION KEYBOARD {ON | OFF}, default is ON
  3889.  
  3890. SETRX    PROC    NEAR            ; translate incoming serial port char
  3891.     mov    ah,cmkey
  3892.     mov    dx,offset trnstab    ; direction table (just one entry)
  3893.     xor    bx,bx            ; no help
  3894.     call    comnd
  3895.     jnc    setrx0            ; nc = success
  3896.     ret                ; failure
  3897. setrx0:    cmp    bx,2            ; Keyboard?
  3898.     jne    setrx0b            ; ne = no
  3899.     jmp    setr11            ; do keyboard
  3900. setrx0b:mov    bx,offset rdbuf        ; our work space
  3901.     mov    dx,offset srxhlp1    ; first help message
  3902.     mov    ah,cmword        ; parse a word
  3903.     call    comnd            ; get incoming byte pattern
  3904.     jnc    setrx0a            ; nc = success
  3905.     ret
  3906. setrx0a:or    ax,ax            ; any text given?
  3907.     jz    setr6            ; nz = no
  3908.     mov    temp,ax            ; save byte count here
  3909.     mov    ax,word ptr rdbuf    ; get first two characters
  3910.     or    ax,2020h        ; convert upper to lower case
  3911.     cmp    ax,'fo'            ; first part of word OFF?
  3912.     je    setr6            ; e = yes, go analyze
  3913.     cmp    ax,'no'            ; word ON?
  3914.     je    setr6            ; e = yes, go do it
  3915.     mov    domath_ptr,offset rdbuf
  3916.     mov    domath_cnt,16
  3917.     mov    domath_msg,1        ; stop messages
  3918.     call    domath            ; convert to number in ax
  3919.     jnc    setr1            ; nc = success    
  3920.     mov    ax,word ptr rdbuf
  3921.     cmp    temp,1            ; just one character given?
  3922. ;;;;;;;    jne    setr6            ; ne = no, so bad code
  3923. setr1:    mov    min,ax            ; save byte code here
  3924.     mov    bx,offset rdbuf        ; our work space
  3925.     mov    dx,offset srxhlp1    ; first help message
  3926.     mov    ah,cmword        ; parse a word
  3927.     call    comnd            ; get incoming byte pattern
  3928.     jnc    setr2            ; nc = success
  3929.     ret                ; failure
  3930. setr2:    or    ax,ax            ; any text given?
  3931.     jz    setr6            ; z = no
  3932.     mov    temp,ax            ; save byte count here
  3933.     mov    domath_ptr,offset rdbuf
  3934.     mov    domath_cnt,ax
  3935.     mov    domath_msg,1        ; stop messages
  3936.     call    domath            ; convert to number in ax
  3937.     jnc    setr3            ; nc = success
  3938.     mov    ax,word ptr rdbuf
  3939.     cmp    temp,1            ; just one character given?
  3940. ;;;;;    jne    setr6            ; ne = no, so bad code or ON/OFF
  3941. setr3:    mov    max,ax            ; save byte code here
  3942.     mov    ah,cmeol        ; get a confirm
  3943.     call    comnd
  3944.     jnc    setr3a            ; nc = success
  3945.     ret                ; failure
  3946. setr3a:    mov    bx,min            ; bl = incoming byte code
  3947.     xor    bh,bh
  3948.     mov    ax,max            ; al = local (translated) byte code
  3949.     mov    rxtable [bx],al        ; store in rx translate table
  3950.     clc                ; success
  3951.     ret
  3952.  
  3953. setr6:    mov    ah,cmeol        ; get a confirm
  3954.     call    comnd
  3955.     jnc    setr6a            ; nc = success
  3956.     ret                ; failure
  3957. setr6a:    mov    dx,offset badrx        ; assume bad construction
  3958.     or    word ptr rdbuf,2020h    ; convert to lower case
  3959.     or    rdbuf+2,20h        ; first three chars
  3960.     cmp    word ptr rdbuf,'fo'    ; key word OFF?
  3961.     jne    setr8            ; ne = no
  3962.     cmp    rdbuf+2,'f'        ; last letter of OFF?
  3963.     jne    setr8            ; ne = no
  3964.     mov    rxtable+256,0        ; OFF is status byte = zero
  3965.     mov    dx,offset rxoffmsg    ; say translation is turned off
  3966.     jmp    short setr9
  3967. setr8:    cmp    word ptr rdbuf,'no'    ; keyword ON?
  3968.     jne    setr9a            ; ne = no, error
  3969.     mov    rxtable+256,1        ; ON is status byte non-zero
  3970.     mov    dx,offset rxonmsg    ; say translation is turned on
  3971. setr9:    cmp    taklev,0        ; executing from a Take file?
  3972.     je    setr9a            ; e = no
  3973.     cmp    flags.takflg,0        ; echo contents of Take file?
  3974.     je    setr10            ; e = no
  3975. setr9a:    mov    ah,prstr        ; bad number message
  3976.     int    dos
  3977. setr10:    clc
  3978.     ret
  3979. setr11:    mov    ah,cmkey        ; SET TRANSLATION KEYBOARD
  3980.     mov    dx,offset ontab        ; on/off
  3981.     xor    bx,bx
  3982.     call    comnd
  3983.     jnc    setr12            ; nc = success
  3984.     ret
  3985. setr12:    push    bx
  3986.     mov    ah,cmeol        ; get a confirm
  3987.     call    comnd
  3988.     pop    bx
  3989.     jnc    setr13            ; nc = success
  3990.     ret                ; failure
  3991. setr13:    mov    flags.xltkbd,bl        ; set keyboard translation on/off
  3992.     clc
  3993.     ret
  3994. SETRX    ENDP
  3995.  
  3996. ; SET TRANSMIT {FILL, LF, Prompt} {ON, OFF, or value}
  3997. SETXMIT    proc    near
  3998.     mov    dx,offset xmitab    ; TRANSMIT keyword table
  3999.     xor    bx,bx
  4000.     mov    ah,cmkey        ; get keyword
  4001.     call    comnd
  4002.     jnc    setxmi1            ; nc = success
  4003.     ret
  4004. setxmi1:cmp    bl,2            ; SET TRANSMIT PROMPT?
  4005.     jne    setxmi2            ; ne = no
  4006.     mov    ah,cmword
  4007.     mov    bx,offset rdbuf        ; put answer here
  4008.     mov    dx,offset xpmthlp
  4009.     call    comnd
  4010.     jc    setxmi1d        ; c = error
  4011.     push    ax            ; save length
  4012.     mov    ah,cmeol        ; get a confirm
  4013.     call    comnd
  4014.     pop    cx            ; recover length to cx
  4015.     jc    setxmi1d        ; c = failure
  4016.     mov    al,rdbuf
  4017.     cmp    cx,1            ; a single char?
  4018.     je    setxmi1c        ; e = yes, use it as the prompt char
  4019.     mov    domath_ptr,offset rdbuf
  4020.     mov    domath_cnt,cx
  4021.     call    domath            ; convert to number in ax
  4022.     jc    setxmi1d        ; c = no number, error
  4023. setxmi1c:mov    script.xmitpmt,al    ; store new prompt value
  4024. setxmi1d:ret
  4025.  
  4026. setxmi2:cmp    bl,1            ; LF?
  4027.     jne    setxmi3            ; ne = no
  4028.     mov    dx,offset ontab        ; on or off table
  4029.     xor    bx,bx
  4030.     call    keyend
  4031.     jc    setxmi2a        ; c = failure
  4032.     mov    script.xmitlf,bl    ; set the xmitlf flag
  4033. setxmi2a:ret
  4034.  
  4035. setxmi3:cmp    bl,0            ; FILL?
  4036.     jne    setxmi8            ; ne = no
  4037.     mov    ah,cmword        ; FILL, get a word sized token
  4038.     mov    bx,offset rdbuf        ; put it here
  4039.     mov    dx,offset xfilhlp    ; help
  4040.     call    comnd
  4041.     jc    setxmix            ; c = failure
  4042.     push    ax            ; save length in ah
  4043.     mov    ah,cmeol        ; get a confirm
  4044.     call    comnd
  4045.     pop    ax
  4046.     jc    setxmix            ; c = failure
  4047.     cmp    ax,1            ; just one character?
  4048.     ja    setxmi4            ; a = no, there's more
  4049.     mov    al,rdbuf        ; get the char
  4050.     mov    script.xmitfill,al    ; store Fill char
  4051.     ret
  4052. setxmi4:mov    ax,word ptr rdbuf
  4053.     or    ax,2020h        ; to lower
  4054.     cmp    ax,'on'            ; "none"?
  4055.     jne    setxmi5            ; ne = no
  4056.     mov    script.xmitfill,0    ; no Filling
  4057.     ret
  4058. setxmi5:cmp    ax,'ps'            ; "space"?
  4059.     jne    setxmi6            ; ne = no
  4060.     mov    script.xmitfill,' '    ; use space as filler
  4061.     ret
  4062. setxmi6:mov    domath_ptr,offset rdbuf
  4063.     mov    domath_cnt,17
  4064.     call    domath            ; convert to number in ax
  4065.     jc    setxmix            ; c = no number, error
  4066.     mov    script.xmitfill,al    ; set the xmitfill flag
  4067.     ret
  4068. setxmi8:mov    ah,cmword        ; PAUSE milliseconds
  4069.     mov    bx,offset rdbuf        ; put answer here
  4070.     mov    dx,offset xpauhlp
  4071.     call    comnd
  4072.     jc    setxmix            ; c = error
  4073.     push    ax            ; save length
  4074.     mov    ah,cmeol        ; get a confirm
  4075.     call    comnd
  4076.     pop    cx            ; recover length to cx
  4077.     jc    setxmix            ; c = failure
  4078.     mov    domath_ptr,offset rdbuf
  4079.     mov    domath_cnt,cx
  4080.     call    domath            ; convert to number in ax
  4081.     jc    setxmix            ; c = no number, error
  4082.     mov    script.xmitpause,ax    ; set the xmitpause flag
  4083. setxmix:ret
  4084. SETXMIT    endp
  4085.  
  4086. ; SET UNKNOWN-CHARACTER-SET {DISCARD, KEEP}, default is KEEP
  4087. unkchset proc    near
  4088.     mov    dx,offset unkctab    ; keep/reject keyword table
  4089.     mov    bx,offset unkchhlp
  4090.     call    keyend
  4091.     jc    unkchx            ; c = failure
  4092.     mov    flags.unkchs,bl        ; 0 = keep, else reject
  4093. unkchx:    ret
  4094. unkchset endp
  4095.  
  4096. ; Common routine for parsing numerical input
  4097. ; Enter with numhlp = offset of help message, numerr = offset of optional
  4098. ;  error message, min, max = allowable range of values.
  4099. ; Returns value in ax, or does parse error return.
  4100. ; Changes ax,bx,dx,si.            [jrd] 18 Oct 1987
  4101. num0:    mov    bx,offset rdbuf        ; where to put text
  4102.     mov    dx,numhlp        ; help text
  4103.     mov    ah,cmword        ; get a word
  4104.     call    comnd
  4105.     push    ax            ; save string count
  4106.     mov    ah,cmeol
  4107.     call    comnd            ; Get a confirm
  4108.     pop    ax
  4109.     jc    num0x            ; c = failure
  4110.     call    numwd
  4111. num0x:    ret
  4112.                     ; second entry point
  4113.  
  4114. ; routine to print an error message, then exit without error status
  4115. ; expects message in dx
  4116. reterr    proc    near
  4117.     mov    ah,prstr
  4118.     int    dos
  4119.     clc
  4120.     ret
  4121. reterr    endp
  4122.  
  4123. code    ends
  4124.  
  4125. code1    segment
  4126.  
  4127. ; Add an entry to a keyword table
  4128. ; enter with bx = table address, dx = ptr to new entry, macptr = string seg,
  4129. ; mccptr = offset of free bytes in table mcctab.
  4130. ; no check is made to see if the entry fits in the table.
  4131. addtab    proc    far
  4132.     push    cx
  4133.     push    si
  4134.     push    es
  4135.     push    bp
  4136.     cld
  4137.     mov    ax,ds
  4138.     mov    es,ax        ; address data segment
  4139.     mov    bp,bx        ; remember where macro name table starts
  4140.     mov    cl,[bx]        ; pick up length of table
  4141.     xor    ch,ch
  4142.     inc    bx        ; point to actual table
  4143.     jcxz    addta4        ; cx = 0 if table is presently empty
  4144.  
  4145. addta1:    push    cx        ; preserve count
  4146.     mov    si,dx        ; point to entry
  4147.     lodsw            ; get length of new entry
  4148.     mov    cx,[bx]        ; and length of table entry
  4149.     cmp    ax,cx        ; are they the same?
  4150.     lahf            ; remember result of comparison
  4151.     jae    addta2        ; is new smaller? ae = no, use table length
  4152.     mov    cx,ax        ; else use length of new entry
  4153. addta2:    lea    di,[bx+2]    ; point to actual keyword
  4154.     repe    cmpsb        ; compare strings
  4155.     pop    cx        ; restore count
  4156.     jb    addta4        ; below, insert before this one
  4157.     jne    addta3        ; not below or same, keep going
  4158.     sahf            ; same. get back result of length comparison
  4159.     jb    addta4        ; if new len is smaller, insert here
  4160.     jne    addta3        ; if not same size, keep going
  4161.     mov    si,bx        ; else this is where entry goes
  4162.     jmp    short addta6    ; no insertion required
  4163. addta3:    mov    ax,[bx]        ; length of keyword
  4164.     add    bx,ax        ; skip this entry
  4165.     add    bx,4        ; length word and 16 bit value
  4166.     loop    addta1        ; and keep looking
  4167. addta4:    mov    si,bx        ; this is first location to move
  4168.     mov    di,bx
  4169.     inc    ds:byte ptr [bp] ; remember we're adding one
  4170.     jcxz    addta6        ; z = no more entries, forget this stuff
  4171. addta5:    mov    bx,[di]        ; get length
  4172.     lea    di,[bx+di+4]    ; end is origin + length + 4 for len, value
  4173.     loop    addta5        ; loop thru remaining keywords
  4174.     mov    cx,di
  4175.     sub    cx,si        ; compute # of bytes to move
  4176.     push    si        ; preserve loc for new entry
  4177.     mov    si,di        ; first to move is last
  4178.     dec    si        ; minus one
  4179.     mov    di,dx        ; new entry
  4180.     mov    bx,[di]        ; get length
  4181.     lea    di,[bx+si+4]    ; dest is source + length of new + 4
  4182.     std            ; move backward
  4183.     rep    movsb        ; move the table down (compress it)
  4184.     cld            ; put flag back
  4185.     pop    si
  4186. addta6:    mov    di,si        ; this is where new entry goes
  4187.     mov    si,dx        ; this is where it comes from
  4188.     mov    cx,[si]        ; length of name
  4189.     add    cx,2        ; include count byte
  4190.     add    mccptr,cx    ; update free space pointer: cnt+name
  4191.     rep    movsb        ; insert new entry
  4192.     mov    ax,macptr    ; and string address
  4193.     stosw
  4194.     add    mccptr,2    ; plus string address
  4195.     pop    bp
  4196.     pop    es
  4197.     pop    si
  4198.     pop    cx
  4199.     ret
  4200. addtab    endp
  4201.  
  4202. ; If new keyword matches an existing one then remove existing keyword,
  4203. ; its string definition, compress tables mcctab and macbuf, readjust string
  4204. ; pointers for each macro name, reduce number of macro table entries by one.
  4205. ; Enter with DI pointing at length word of mac name (followed by mac name).
  4206. ; Otherwise, exit with no changes.  13 June 1987 [jrd]
  4207. remtab    proc    far
  4208.     push    ax
  4209.     push    bx
  4210.     push    cx
  4211.     push    si
  4212.     push    di
  4213.     push    temp            ; preserve
  4214.     mov    bx,offset mcctab+1    ; table of macro keywords
  4215.     mov    temp,0            ; temp = current keyword
  4216.     cmp    byte ptr mcctab,0    ; any macros defined?
  4217.     jne    remta1            ; ne = yes
  4218.     jmp    remtax            ; else exit now
  4219. remta1:                    ; match table keyword and text word
  4220.     mov    si,di            ; pointer to user's cnt+name
  4221.     mov    cx,[si]            ; length of user's macro name
  4222.     jcxz    remtax            ; empty macro name to remove
  4223.     add    si,2            ; point to new macro name
  4224.     cmp    cx,[bx]            ; compare length vs table keyword
  4225.     jne    remta4            ; ne = not equal lengths, try another
  4226.     push    si            ; lengths match, how about spelling?
  4227.     push    bx
  4228.     add    bx,2            ; point at start of keyword
  4229. remta2:    mov    ah,[bx]            ; keyword char
  4230.     mov    al,[si]            ; new text char
  4231.     cmp    al,ah            ; test characters
  4232.     jne    remta3            ; ne = no match
  4233.     inc     si            ; move to next char
  4234.     inc    bx
  4235.     loop    remta2            ; loop through entire length
  4236. remta3:    pop    bx
  4237.     pop    si
  4238.     jcxz    remta6            ; z: cx = 0, exit with match;
  4239.                     ;  else select next keyword
  4240. remta4:    inc    temp            ; number of keyword to test next
  4241.     mov    cx,temp
  4242.     cmp    cl,mcctab        ; all done? Recall, temp starts at 0
  4243.     jb    remta5            ; b = not yet
  4244.     jmp    remtax            ; exhausted search, unsuccessfully
  4245. remta5:    mov    ax,[bx]            ; cnt (keyword length from macro)
  4246.     add    ax,4            ; skip count and word pointer
  4247.     add    bx,ax            ; bx = start of next keyword slot
  4248.     jmp    short remta1        ; do another comparison
  4249.                     ; new name already present as a macro
  4250. remta6:    cld                ; clear macro string and macro name
  4251.     push    ds
  4252.     pop    es            ; set es to data segment
  4253.     mov    temp,bx            ; save ptr to found keyword
  4254.     mov    ax,[bx]            ; cnt (keyword length of macro)
  4255.     add    ax,2            ; skip cnt
  4256.     add    bx,ax            ; point to string segment field
  4257.     add    ax,2            ; count segment field bytes
  4258.     sub    mccptr,ax        ; readjust free space ptr for names
  4259.     push    bx
  4260.     push    es
  4261.     mov    es,[bx]            ; segment of string
  4262.     mov    ax,ds            ; check for being in our data segment
  4263.     cmp    ax,[bx]            ; same as our data seg?
  4264.     je    remta7            ; e = yes, don't free that
  4265.     mov    ah,freemem        ; free that memory block
  4266.     int    dos
  4267. remta7:    pop    es
  4268.     pop    bx
  4269.                     ; clear keyword table mcctab
  4270.     add    bx,2            ; compute source = next keyword
  4271.     mov    si,bx            ; address of next keyword
  4272.     mov    di,temp            ; address of found keyword
  4273.     mov    cx,offset mcctab+mcclen ; address of buffer end
  4274.     sub    cx,si            ; amount to move
  4275.     jcxz    remtax            ; cx = 0 means none
  4276.     rep    movsb            ; move down keywords (deletes current)
  4277.     dec    mcctab            ; one less keyword
  4278. remtax:    pop    temp            ; recover temp variable
  4279.     pop    di
  4280.     pop    si
  4281.     pop    cx
  4282.     pop    bx
  4283.     pop    ax
  4284.     ret
  4285. remtab    endp
  4286.  
  4287. ; Renames macros \%0..\%9 by changing the first two characters of the name
  4288. ; to be <null><taklev>. Used to preserve old \%n macros and not show them.
  4289. ; Return carry set if nothing is hidden.
  4290. hidemac proc    far
  4291.     push    bx
  4292.     push    cx
  4293.     push    temp
  4294.     mov    byte ptr temp,'0'    ; start with this \%0 name
  4295. hidema1:mov    bx,offset mcctab+1    ; table of macro names, skip count
  4296.     mov    cl,mcctab        ; number of entries
  4297.     xor    ch,ch
  4298.     jcxz    hidema6            ; z = empty table
  4299.  
  4300. hidema2:cmp    word ptr [bx],3        ; name length, do three byte names
  4301.     jne    hidema3            ; ne = not three chars
  4302.     cmp    word ptr [bx+2],'%\'    ; starts with correct prefix?
  4303.     jne    hidema3            ; ne = no
  4304.     mov    al,byte ptr [bx+4]    ; third char of name
  4305.     cmp    al,byte ptr temp    ; matches name?
  4306.     je    hidema4            ; e = yes
  4307. hidema3:mov    ax,[bx]            ; get length of name
  4308.     add    ax,4            ; plus count and word pointer
  4309.     add    bx,ax            ; point to next entry
  4310.     loop    hidema2
  4311.     jmp    short hidema5
  4312. hidema4:call    hidewrk            ; call worker to hide macro
  4313. hidema5:inc    byte ptr temp
  4314.     cmp    byte ptr temp,'9'    ; all done?
  4315.     jbe    hidema1            ; be = no
  4316. hidema6:pop    temp
  4317.     pop    cx
  4318.     pop    bx
  4319.     ret
  4320. hidemac    endp
  4321.  
  4322. ; Hide existing macro. Enter with BX pointing to entry slot in mcctab,
  4323. ; uses settemp as temp workspace.
  4324. ; Used by hidemac and localmac. 
  4325. hidewrk    proc    far
  4326.     push    bx
  4327.     push    cx
  4328.     push    si
  4329.     push    di
  4330.     mov    di,bx            ; need di for remtab
  4331.     mov    ax,[bx]            ; original count word
  4332.     mov    cx,ax
  4333.     add    ax,2            ; plus new prefix
  4334.     mov    si,offset settemp
  4335.     mov    [si],ax            ; len = old length plus <null><level>
  4336.     xor    al,al            ; prepare new prefix
  4337.     mov    ah,taklev        ; of <null><taklev>
  4338.     mov    [si+2],ax        ; new prefix
  4339.     add    si,4            ; count and prefix
  4340. hidewr1:mov    al,[bx+2]        ; copy old name after prefix
  4341.     mov    [si],al
  4342.     inc    bx
  4343.     inc    si
  4344.     loop    hidewr1
  4345.  
  4346.           mov    bx,di
  4347.     mov    ax,[bx]            ; length of name
  4348.     add    ax,2            ; plus name length count word
  4349.     add    bx,ax            ; point at definition segment
  4350.     mov    ax,1            ; smallest allocation
  4351.     call    malloc            ; allocate space as dummy definition
  4352.     mov    cx,[bx]            ; seg of original def to CX
  4353.     mov    [bx],ax            ; seg of dummy def replaces it
  4354.     call    remtab            ; remove macro, di is pointer
  4355.     mov    macptr,cx        ; tell addtab definition segment
  4356.     mov    bx,offset mcctab     ; macro name table
  4357.     mov    dx,offset settemp    ; new name
  4358.     call    addtab        ; create new entry for <null><digit><oldname>
  4359.     pop    di
  4360.     pop    si
  4361.     pop    cx
  4362.     pop    bx
  4363.     ret
  4364. hidewrk    endp
  4365.  
  4366.  
  4367. ; Removes all current \%0..\%9 macros and renames <null><taklev> macros by
  4368. ; removing the first two characters of the names of form <null><taklev>foo.
  4369. ; Used to recover old \%n macros from hidemac and locals from Local.
  4370. unhidemac proc    far
  4371.     push    bx
  4372.     push    cx
  4373.     push    dx
  4374.     push    di                 ; do rename of <null><taklev>foo
  4375. unhide1:mov    di,offset mcctab+1    ; table of macro names, skip count
  4376.     mov    cl,mcctab        ; number of entries
  4377.     xor    ch,ch
  4378.     jcxz    unhide5            ; z = empty table
  4379.     xor    dl,dl            ; dx = macro prefix to examine
  4380.     mov    dh,taklev        ; di => length word, name string
  4381. unhide2:cmp    word ptr [di+2],dx    ; starts with <null><taklev> prefix?
  4382.     jne    unhide4            ; ne = no
  4383.     mov    bx,di
  4384.     mov    cx,[bx]            ; length of definition
  4385.     sub    cx,2            ; skip prefix bytes
  4386.     push    si
  4387.     mov    si,offset settemp    ; destination work buffer
  4388.     mov    [si],cx         ; new length
  4389.     add    si,2            ; have stored count word
  4390.     add    bx,2+2            ; skip count word and prefix
  4391. unhide3:mov    al,[bx]
  4392.     mov    [si],al            ; copy name to temp array
  4393.     inc    si
  4394.     inc    bx
  4395.     loop    unhide3
  4396.     pop    si
  4397.     mov    bx,di
  4398.     add    bx,[bx]            ; skip macro name
  4399.     add    bx,2            ; and count word
  4400.     mov    cx,[bx]            ; cx is now seg of definition
  4401.     mov    ax,1            ; minimal allocation of one byte
  4402.     call    malloc            ; create dummy def
  4403.     mov    [bx],ax            ; write new dummy def segment
  4404.     call    remtab            ; remove prefixed name, DI is ptr
  4405.     mov    di,offset settemp    ; shortened name
  4406.     call    remtab            ; remove unprefixed macro, DI is ptr
  4407.     mov    bx,offset mcctab    ; mac table
  4408.     mov    dx,offset settemp    ; name string
  4409.     mov    macptr,cx        ; segment of definition
  4410.     call    addtab            ; add to table
  4411.     jmp    short unhide1
  4412.  
  4413. unhide4:mov    ax,[di]            ; get length of name
  4414.     add    ax,4            ; plus count and word pointer
  4415.     add    di,ax            ; point to next entry
  4416.     loop    unhide2            ; look at next entry
  4417. unhide5:pop    di
  4418.     pop    dx
  4419.     pop    cx
  4420.     pop    bx
  4421.     ret
  4422. unhidemac endp
  4423.  
  4424. numwd    proc    far            ; worker
  4425.     mov    domath_ptr,offset rdbuf
  4426.     mov    domath_cnt,ax
  4427.     call    domath            ; convert to number in ax
  4428.     jc    num0er            ; c = no number, error
  4429.     cmp    ax,max            ; largest permitted value
  4430.     ja    num0er            ; a = error
  4431.     cmp    ax,min            ; smallest permitted value
  4432.     jb    num0er            ; b = error
  4433.     clc
  4434.     ret                ; return value in ax
  4435.  
  4436. num0er:    mov    dx,numerr        ; comand-specific error message, if any
  4437.     or    dx,dx            ; was any given?
  4438.     jz    num0e1            ; z = no, use generic msg
  4439.     push    ds
  4440.     mov    ax,seg data1        ; where help lives
  4441.     mov    ds,ax
  4442.     mov    ah,prstr
  4443.     int    dos            ; show given error message
  4444.     pop    ds
  4445.     jmp    short num0e2
  4446. num0e1:    mov    dx,offset nummsg1    ; get address of numeric error message
  4447.     push    ds
  4448.     mov    ax,seg data1
  4449.     mov    ds,ax
  4450.     mov    ah,prstr
  4451.     int    dos
  4452.     pop    ds
  4453.     mov    ax,min            ; smallest permitted number
  4454.     call    decout            ; display decimal number in ax
  4455.     mov    ah,prstr
  4456.     push    ds
  4457.     mov    dx,seg nummsg2
  4458.     mov    ds,dx
  4459.     mov    dx,offset nummsg2    ; "and"
  4460.     int    dos
  4461.     pop    ds
  4462.     mov    ax,max            ; largest permitted number
  4463.     call    decout
  4464.     mov    ah,prstr
  4465.     mov    dx,offset crlf
  4466.     int    dos
  4467. num0e2:    stc
  4468.     ret
  4469. numwd    endp
  4470.  
  4471. ; Worker for POP/END and RETURN.
  4472. ; Pop take levels (via takclo) through tails of For/While, back to the
  4473. ; take level of the last DO or prompt command.
  4474. POPLEVEL proc    far
  4475.     cmp    taklev,0        ; in a Take/macro?
  4476.     je    poplevx            ; e = no
  4477.     mov    bx,takadr
  4478.     mov    al,[bx].takinvoke    ; take level of last DO or command
  4479.     mov    ah,[bx].takattr        ; attributes
  4480.     cmp    taklev,al        ; Take level now versus last DO
  4481.     jb    poplevx            ; b = have exited macro already
  4482.     push    ax
  4483.     call    takclos            ; close current Macro/Take
  4484.     pop    ax
  4485.     test    ah,take_while+take_subwhile ; closed While/For/Switch?
  4486.     jz    poplevx            ; z = no
  4487.     mov    bx,takadr
  4488.     test    [bx].takattr,take_while+take_subwhile ; for/while macro?
  4489.     jnz    poplevel        ; nz = yes, exit for/while too
  4490. poplevx:clc
  4491.     ret
  4492. POPLEVEL endp
  4493.  
  4494. FDECLARE    proc    far        ; declare array \&<char @a..z>[size]
  4495.     or    ax,ax            ; null entry?
  4496.     jnz    decl2
  4497.     stc                ; fail
  4498.     ret
  4499. decl2:    cmp    rdbuf[3],'&'        ; syntax checking
  4500.     jne    declf            ; ne = fail
  4501.     cmp    rdbuf[5],'['        ; size bracket?
  4502.     jne    declf            ; ne = no, fail
  4503.     and    rdbuf[4],not 20h    ; to upper case
  4504.     mov    al,rdbuf[4]        ; array name
  4505.     cmp    al,'A'            ; range check
  4506.     jb    declf
  4507.     cmp    al,'Z'
  4508.     ja    declf
  4509.     mov    si,offset rdbuf[6]    ; point at size number
  4510.     xor    ah,ah
  4511.     mov    cx,128            ; limit scan
  4512. decl3:    lodsb
  4513.     cmp    al,']'            ; closing bracket?
  4514.     je    decl4            ; e = yes
  4515.     inc    ah            ; count byte
  4516.     loop    decl3            ; keep looking
  4517.     jmp    declf            ; fail if got here
  4518. decl4:    xor    al,al
  4519.     xchg    ah,al
  4520.     sub    si,ax            ; point at start of number
  4521.     dec    si
  4522.     mov    domath_ptr,si
  4523.     mov    domath_cnt,ax
  4524.     call    domath            ; convert to number in ax
  4525.     jnc    decl5            ; nc = success, value is in DX:AX
  4526.     ret                ; fail
  4527. decl5:    or    dx,dx            ; too large a value?
  4528.     jnz    decl5a            ; nz = yes
  4529.     cmp    ax,32000        ; 32000 max
  4530.     jbe    decl5b            ; be = in range
  4531. decl5a:    mov    dx,offset arraybad    ; say too large
  4532.     mov    ah,prstr
  4533.     int    dos
  4534.     jmp    declf            ; fail
  4535. decl5b:    mov    bl,rdbuf[4]
  4536.     sub    bl,'@'            ; remove bias
  4537.     js    declf            ; s = sign, failure
  4538.     xor    bh,bh            ; preserve bx til end of proc
  4539.     shl    bx,1            ; address words
  4540.     call    decl20            ; call remover
  4541.     cmp    ax,0            ; index of zero to clear the array?
  4542.     je    decl6            ; e = yes, done
  4543.     inc    ax            ; create one more than [value]
  4544.     call    decl10            ; call creator
  4545. decl6:    ret
  4546. declf:    stc                ; failure
  4547.     ret
  4548.  
  4549. decl20    proc    near            ; remove array
  4550.     push    ax            ; save size in ax
  4551.     push    es
  4552.     mov    si,marray[bx]        ; get segment of array's definition
  4553.     or    si,si            ; anything present?
  4554.     jz    decl23            ; no, no need to undefine anything
  4555.     mov    es,si
  4556.     mov    cx,es:[0]        ; get number of elements
  4557.     jcxz    decl23            ; z = none, unlikely
  4558.     xor    si,si            ; count word (number of elements)
  4559. decl21:    add    si,2            ; point to slot holding string seg
  4560.     mov    ax,es:[si]        ; get string seg
  4561.     or    ax,ax            ; null?
  4562.     jz    decl22            ; z = yes, ignore
  4563.     mov    word ptr es:[si],0    ; clear string seg pointer
  4564.     push    es
  4565.     mov    es,ax            ; segment
  4566.     mov    ah,freemem        ; free the memory
  4567.     int    dos
  4568.     pop    es
  4569. decl22:    loop    decl21
  4570.     xor    ax,ax            ; get a zero
  4571.     xchg    ax,marray[bx]        ; clear array seg storage pointer
  4572.     mov    es,ax
  4573.     mov    ah,freemem        ; free storage pointer memory
  4574.     int    dos
  4575. decl23:    pop    es
  4576.     pop    ax
  4577.     clc                ; end removing array
  4578.     ret
  4579. decl20    endp
  4580.  
  4581. decl10    proc    near            ; creator
  4582.     push    ax            ; save ax
  4583.     inc    ax            ; number of elements plus one size int
  4584.     shl    ax,1            ; count bytes for malloc
  4585.     call    malloc            ; get seg of memory to ax
  4586.     pop    cx            ; array size (was in ax)
  4587.     jc    decl12            ; c = failed
  4588.     mov    marray[bx],ax        ; remember storage area
  4589.     push    es
  4590.     push    di
  4591.     mov    es,ax            ; segment of new memory
  4592.     mov    es:[0],cx        ; write size of array as 1st word
  4593.     mov    di,2            ; offset of string seg pointers
  4594.     xor    ax,ax
  4595.     cld
  4596.     rep    stosw            ; clear the array
  4597.     pop    di
  4598.     pop    es
  4599.     clc
  4600. decl12:    ret                ; can return carry set from failure
  4601. decl10    endp
  4602. FDECLARE endp
  4603.  
  4604. ; define contents of array element. Command line is in rdbuf+2 as
  4605. ; \&<char>[index] definition, from dodef. Length of line is in cx.
  4606.  
  4607. defarray proc    far
  4608.     cmp    rdbuf[3],'&'        ; syntax checking
  4609.     jne    defarf            ; ne = fail
  4610.     cmp    rdbuf[5],'['        ; size bracket?
  4611.     jne    defarf            ; ne = no, fail
  4612.     and    rdbuf[4],not 20h    ; to upper case
  4613.     mov    al,rdbuf[4]        ; array name
  4614.     cmp    al,'A'            ; range check
  4615.     jb    defarf
  4616.     cmp    al,'Z'
  4617.     ja    defarf
  4618.     mov    si,offset rdbuf[6]    ; point at size number
  4619.     xor    ah,ah
  4620.     cld
  4621. defar3:    lodsb
  4622.     cmp    al,']'            ; closing bracket?
  4623.     je    defar4            ; e = yes
  4624.     inc    ah            ; count byte
  4625.     loop    defar3            ; keep looking
  4626.     jmp    defarf            ; fail if got here
  4627. defar4:    xor    al,al            ; cx has chars remaining in cmd line
  4628.     xchg    ah,al
  4629.     mov    di,si            ; save di as start of definition space
  4630.     sub    si,ax            ; point at start of number
  4631.     dec    si
  4632.     mov    domath_ptr,si
  4633.     mov    domath_cnt,ax
  4634.     call    domath            ; do string to binary dx:ax
  4635.     jnc    defar5            ; nc = success, value is in DX:AX
  4636.     ret                ; fail
  4637. defar5:    mov    temp,ax            ; save index value
  4638.     mov    bl,rdbuf[4]        ; get array name letter
  4639.     sub    bl,'@'            ; remove bias
  4640.     xor    bh,bh            ; preserve bx til end of proc
  4641.     shl    bx,1            ; address words
  4642.  
  4643. defar6:    call    defar_rem        ; clear current definition, if any
  4644.     inc    di            ; skip space between name and def
  4645.     mov    dx,di            ; for strlen
  4646.     call    strlen            ; length of definition
  4647.     jcxz    defar7            ; z = no definition, done
  4648.     mov    ax,cx            ; bytes needed
  4649.     add    ax,2+2            ; starts with byte count and elem 0
  4650.     call    malloc            ; get the space
  4651.     jc    defarf            ; c = failed
  4652.     mov    si,marray[bx]        ; segment of array
  4653.     or    si,si            ; if any
  4654.     jz    defar7            ; z = none
  4655.     push    es
  4656.     mov    es,si
  4657.     mov    si,temp            ; array index
  4658.     shl    si,1            ; index words
  4659.     mov    es:[si+2],ax        ; remember segment of string def
  4660.     mov    es,ax            ; string definition seg
  4661.     mov    es:[0],cx        ; length of string
  4662.     mov    si,di            ; start of string text
  4663.     mov    di,2            ; destination
  4664.     cld
  4665.     rep    movsb            ; copy to malloc'd space
  4666.     pop    es
  4667. defar7:    clc                ; success
  4668.     ret
  4669. defarf:    mov    kstatus,ksgen        ; general command failure
  4670.     stc                ; failure exit
  4671.     ret
  4672.  
  4673. ; Remove string definition. Enter with BX holding array name index, and
  4674. ; TEMP holding array index.
  4675. defar_rem proc    near            ; remove definition of array element
  4676.     push    ax            ; undefining string within array
  4677.     push    si
  4678.     push    es
  4679.     mov    ax,marray[bx]        ; current array seg
  4680.     or    ax,ax            ; if any
  4681.     jz    defar_rem1        ; z = none
  4682.     mov    si,temp            ; index value
  4683.     shl    si,1            ; index words
  4684.     mov    es,ax
  4685.     mov    ax,es:[0]        ; get array size
  4686.     shl    ax,1            ; in words
  4687.     cmp    si,ax            ; index versus size
  4688.     ja    defar_rem1        ; a = out of bounds, ignore
  4689.     xor    ax,ax            ; get a zero
  4690.     xchg    ax,es:[si+2]        ; get string's segment to ax, clr ref
  4691.     or    ax,ax            ; anything there?
  4692.     jz    defar_rem1        ; z = no
  4693.     mov    es,ax            ; seg to es for DOS
  4694.     mov    ah,freemem        ; free string space
  4695.     int    dos
  4696. defar_rem1:
  4697.     pop    es
  4698.     pop    si
  4699.     pop    ax
  4700.     ret
  4701. defar_rem endp
  4702.  
  4703. defarray endp
  4704.  
  4705. ; Revise string in ES:SI et seq. Expect incoming length to be in CX.
  4706. ; Original string modified to replace bare commas with Carriage Returns.
  4707. ; Top level braces removed, but only if the string begins with an 
  4708. ; opening brace, and hence commas revealed are also converted to CR.
  4709. ; A null is forced at the end of the string.
  4710. ; All registers preserved except CX (returned length).
  4711. docnv    proc    far
  4712.     push    ax
  4713.     push    bx
  4714.     push    dx
  4715.     push    si            ; src domacptr:0,2
  4716.     push    di
  4717.     xor    bx,bx            ; brace count (bl), paren (bh)
  4718.     mov    dl,braceop        ; opening brace (we count them up)
  4719.     mov    dh,bracecl        ; closing brace (we count them down)
  4720.     mov    cx,es:[si]        ; get string length
  4721.     jcxz    docnv9            ; z = empty
  4722.     add    si,2            ; where text starts
  4723.     mov    di,si            ; si = source
  4724.     cld
  4725.     mov    ah,es:[si]        ; record opening char
  4726. docnv2:    mov    al,es:[si]        ; read a char
  4727.     cmp    al,dl            ; opening brace?
  4728.     jne    docnv3            ; ne = no
  4729.     inc    bl            ; count brace level
  4730.     cmp    bl,1            ; first level?
  4731.     jne    docnv7            ; ne = no, write intact
  4732.     or    bh,bh            ; in parens?
  4733.     jnz    docnv7            ; nz = yes, don't replace
  4734.     cmp    ah,dl            ; started with opening brace?
  4735.     jne    docnv7            ; ne = no, don't replace brace
  4736.     jmp    short docnv8        ; skip opening brace
  4737. docnv3:    cmp    al,dh            ; closing brace?
  4738.     jne    docnv4            ; ne = no
  4739.     dec    bl            ; count down
  4740.     or    bl,bl            ; still within braces?
  4741.     jg    docnv7            ; g = yes, write intact
  4742.     xor    bx,bx            ; found brace match, reset to zero
  4743.     cmp    ah,dl            ; started with opening brace?
  4744.     jne    docnv7            ; ne = no, write brace
  4745.     jmp    short docnv8        ; omit the brace
  4746. docnv4:    cmp    al,'('            ; opening paren?
  4747.     jne    docnv5            ; ne = no
  4748.     inc    bh            ; count paren level
  4749.     jmp    short docnv7
  4750. docnv5:    cmp    al,')'            ; closing paren?
  4751.     jne    docnv6            ; ne = no
  4752.     dec    bh
  4753.     cmp    bh,0            ; below 0?
  4754.     jg    docnv7            ; g = no, still in paren
  4755.     xor    bh,bh            ; in case underrun, reset to zero
  4756.     jmp    docnv7            ; matching paren
  4757. docnv6:    cmp    al,','            ; comma?
  4758.     jne    docnv7            ; ne = no
  4759.     or    bh,bh            ; in paren clause?
  4760.     jnz    docnv7            ; nz = yes, treat comma as literal
  4761.     cmp    bl,1            ; in braced clause?
  4762.     ja    docnv7            ; a = yes, treat comma as literal
  4763.     mov    al,CR            ; replace bare comma with CR
  4764. docnv7:    mov    es:[di],al
  4765.     inc    di            ; next destination byte
  4766. docnv8:    inc    si            ; next input byte
  4767.     loop    docnv2            ; do more
  4768. docnv9:    mov    cx,di            ; ending place + 1
  4769.     pop    di
  4770.     pop    si            ; start of buffer
  4771.     sub    cx,si
  4772.     sub    cx,2            ; minus count word
  4773.     mov    es:[si],cx        ; string length
  4774.     pop    dx
  4775.     pop    bx
  4776.     pop    ax
  4777.     clc
  4778.     ret
  4779. docnv    endp
  4780.  
  4781. code1    ends
  4782.     end
  4783.