home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
mskermit.tar.gz
/
mskermit.tar
/
mssset.asm
< prev
next >
Wrap
Assembly Source File
|
1998-05-28
|
142KB
|
4,783 lines
NAME mssset
; File MSSSET.ASM
include mssdef.h
; Copyright (C) 1982, 1997, Trustees of Columbia University in the
; City of New York. The MS-DOS Kermit software may not be, in whole
; or in part, licensed or sold for profit as a software product itself,
; nor may it be included in or distributed with commercial products
; or otherwise distributed by commercial concerns to their clients
; or customers without written permission of the Office of Kermit
; Development and Distribution, Columbia University. This copyright
; notice must not be removed, altered, or obscured.
;
; Edit history
; 12 Jan 1995 version 3.14
; Last edit
; 12 Jan 1995
public setcom, prmptr, dodef, setcpt, docom, stkadr, rdbuf, reset
public setrx, rxtable, srvdsa, srvena, mcctab, takclos, ask
public askq, assign, initibm, mccptr, setinpbuf, setrollb, npages
public xfchtab, xftyptab, com1port, com2port, com3port, com4port
public flotab, popcmd, domacptr, warntab, portirq, portfifo, dodecom
public xfertab1, xfertab2, xfertab3, rollwidth, setwidth, abftab
public localmac, getok, takeerror, macroerror, getc, dial, docnv
public takopen_sub, takopen_file, takopen_macro, _forinc, poplevel
public hide_assign, hide_define, declare, marray, forcmd, undefine
ifndef no_tcp
public tcpaddress,tcpsubnet,tcpdomain,tcpgateway,tcpprimens
public tcpsecondns,tcphost,tcpbcast,tcpport,tcppdint,tcpttbuf
public tcpbtpserver,tcpnewline,tcpdebug,tcpmode,tcpmss
endif ; no_tcp
braceop equ 7bh ; opening curly brace
bracecl equ 7dh ; closing curly brace
maketab MACRO ; Assembler Macro to make rxtable [jrd]
cnt = 0
rept 256
db cnt ; initialize table to 0 .. 255
cnt = cnt + 1
endm
db 0 ; table off (0) or on (1) indicator
ENDM
data segment
extrn comand:byte, flags:byte, trans:byte, takadr:word, taklev:byte
extrn portval:word, dtrans:byte, spause:word, machnam:byte
extrn filtst:byte, maxtry:byte, script:byte, denyflg:word
extrn sloghnd:word, ploghnd:word, tloghnd:word, cardet:byte
extrn decbuf:byte, kstatus:word, errlev:byte, srvtmo:byte
extrn luser:byte, lpass:byte, destab:byte, blktab:byte
extrn seoftab:byte, dmpname:byte, lsesnam:byte, lpktnam:byte
extrn ltranam:byte, incstb:byte, inactb:byte, rxoffmsg:byte
extrn rxonmsg:byte, scpbuflen:word, setchtab:byte
extrn prnname:byte, prnhand:word, outpace:word, apctrap:byte
extrn protlist:byte, rcvpathflg:byte, sndpathflg:byte
extrn fossilflag:byte, ifelse:byte, oldifelse:byte
extrn domath_ptr:word, domath_cnt:word, domath_msg:word
rxtable equ THIS BYTE ; build 256 byte Translation Input table
maketab ; table rxtable is used by Connect mode
kerm db 'MS-Kermit>',0 ; default ASCIIZ prompt
promptbuf db 80 dup (0),0 ; buffer for new ASCIIZ prompt
rdbuf db cmdblen dup (?) ; work space; room for macro def
; and for Status display line
settemp db 100 dup (0) ; temp for hidemac/unhide
stflg db 0 ; Says if setting SEND or RECEIVE parameter
defkind db 0 ; 0 for ASSIGN, 1 for DEFINE
ermes1 db cr,lf,'?Too many macro names$'
ermes2 db cr,lf,bell,'?No room for Take file buffer or Macro definition'
db cr,lf,bell,'$'
ermes4 db cr,lf,'?Too many active Take files and Macros',cr,lf, bell,'$'
ermes5 db cr,lf,'?Not implemented$'
ermes6 db cr,lf,'?More parameters are needed$'
ermes7 db cr,lf,'?Cannot use RTS/CTS on non-UART ports$'
ermes8 db cr,lf,'?Cannot use HARDWARE parity on non-UART ports$'
errcap db cr,lf,'?Unable to open that file$'
erropn db cr,lf,'?Log file is already open$'
badrx db cr,lf,'?Expected ON, OFF, or \nnn$'
escerr db cr,lf,'?Not a control code$'
takcerr db cr,lf,'?Note: command is valid only in Take files and Macros$'
dmpdefnam db 'Kermit.scn',0 ; asciiz default screen dump filename
prndefnam db 'PRN',0 ; asciiz default printer name
xfchbad db cr,lf,'Warning: forcing FILE CHARACTER-SET to CP866$'
xfchbad2 db cr,lf,'Warning: forcing FILE CHARACTER-SET to Shift-JIS$'
xfchbad3 db cr,lf,'Warning: forcing FILE CHARACTER-SET to CP862$'
setchmsg db cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to CYRILLIC$'
setchmsg2 db cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to'
db ' Japanese-EUC$'
setchmsg3 db cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to HEBREW-ISO$'
badcntlmsg db cr,lf,'?Number is not in range of 0..31, 128..159$'
getdef db 'Please respond Yes or No ',0 ; ASCII, used as prompt
crlf db cr,lf,'$'
space db ' ',0
srvtab db 2 ; SET SERVER table
mkeyw 'Login',1
mkeyw 'Timeout',2
ifndef no_network
settab db 63 ; Set table
else
settab db 63 - 3 ; Set table
endif ; no_network
mkeyw 'Alarm',setalrm
mkeyw 'Attributes',setatt
mkeyw 'Baud',baudst
mkeyw 'Bell',bellst
mkeyw 'Block-check-type',blkset
mkeyw 'Carrier',setcar
mkeyw 'COM1',com1port
mkeyw 'COM2',com2port
mkeyw 'COM3',com3port
mkeyw 'COM4',com4port
mkeyw 'Control-character',cntlset
mkeyw 'Count',takectr
mkeyw 'Debug',debst
mkeyw 'Default-disk',cwdir
mkeyw 'Delay',setdely
mkeyw 'Destination',desset
mkeyw 'Display',disply
mkeyw 'Dump',setdmp
mkeyw 'Duplex',setdup
mkeyw 'End-of-Line',eolset
mkeyw 'EOF',seteof
mkeyw 'Errorlevel',seterl
mkeyw 'Escape-character',escset
mkeyw 'Exit',setexitwarn
mkeyw 'File',setfile
mkeyw 'Flow-control',floset
mkeyw 'Fossil',fosset
mkeyw 'Handshake',hndset
mkeyw 'Incomplete',abfset
mkeyw 'Input',inpset
mkeyw 'Key',setkey
mkeyw 'Line',coms
mkeyw 'Local-echo',lcal
mkeyw 'Macro',setmacerr
mkeyw 'Mode-line',modl
mkeyw 'Modem',setmodem
ifndef no_network
mkeyw 'NetBios-name',setnbios
endif ; no_network
mkeyw 'Output',setoutput
mkeyw 'Parity',setpar
mkeyw 'Port',coms
mkeyw 'Printer',setprn
mkeyw 'Prompt',promset
mkeyw 'Receive',recset
mkeyw 'Remote',remset
mkeyw 'Repeat',repset
mkeyw 'Retry',retryset
mkeyw 'Rollback',setrollb
mkeyw 'Send',sendset
mkeyw 'Server',setsrv
mkeyw 'Speed',baudst
mkeyw 'Stop-bits',stopbit
mkeyw 'Take',takset
ifndef no_tcp
mkeyw 'TCP/IP',tcpipset
mkeyw 'Telnet',tcpipset
endif ; no_tcp
mkeyw 'Terminal',vts
mkeyw 'Timer',timset
mkeyw 'Transfer',sxfer
mkeyw 'xfer',sxfer ; hidden synonym
mkeyw 'Translation',setrx
mkeyw 'Transmit',setxmit
mkeyw 'Unknown-character-set',unkchset
mkeyw 'Warning',filwar
mkeyw 'Windows',winset
setfitab db 6 ; Set File command table
mkeyw 'Character-Set',1
mkeyw 'Collision',0
mkeyw 'Display',3
mkeyw 'Incomplete',4
mkeyw 'Type',2
mkeyw 'Warning',0
setrep db 2 ; SET REPEAT
mkeyw 'Counts',0
mkeyw 'Prefix',1
xfertab db 4 ; SET TRANSFER table
mkeyw 'Character-set',0
mkeyw 'Locking-shift',1
mkeyw 'Mode',3
mkeyw 'Translation',2
xfertab1 db 3 ; SET TRANSFER LOCKING-SHIFT
mkeyw 'Off',lock_disable
mkeyw 'On',lock_enable
mkeyw 'Forced',lock_force
xfertab2 db 2 ; SET TRANSFER TRANSLATION
mkeyw 'Readable',0
mkeyw 'Invertible',1
xfertab3 db 2 ; SET TRANSFER MODE
mkeyw 'Automatic',1
mkeyw 'Manual',0
xfchtab db 6 ; SET TRANSFER CHARACTER-SET
mkeyw 'Transparent',xfr_xparent ; no translation
mkeyw 'Latin1 ISO 8859-1',xfr_latin1 ; ISO 8859-1, Latin-1
mkeyw 'Latin2 ISO 8859-2',xfr_latin2 ; ISO 8859-2, Latin-2
mkeyw 'Hebrew ISO 8859-8',xfr_hebiso ; ISO 8859-8 Hebrew-ISO
mkeyw 'Cyrillic ISO 8859-5',xfr_cyrillic; ISO 8859-5/Cyrillic, CP866
mkeyw 'Japanese-EUC',xfr_japanese ; Japanese-EUC
xftyptab db 2 ; SET FILE TYPE table
mkeyw 'Binary',1 ; Binary = as-is
mkeyw 'Text',0 ; Text = can change char sets
warntab db 8 ; File Warning table
mkeyw 'Append',filecol_append ; append
mkeyw 'Overwrite',filecol_overwrite ; overwrite
mkeyw 'Rename',filecol_rename ; rename
mkeyw 'Discard',filecol_discard ; discard
mkeyw 'Update',filecol_update ; update (if incoming is newer)
mkeyw 'No-supersede',filecol_discard ; discard
mkeyw 'on (rename)',filecol_rename ; old form
mkeyw 'off (overwrite)',filecol_overwrite ; old form
unkctab db 2 ; unknown character-set disposition
mkeyw 'Keep',0
mkeyw 'Cancel',1
atttab db 7 ; SET ATTRIBUTES table
mkeyw 'Off',00ffh ; all off
mkeyw 'On',10ffh ; all on (high byte is on/off)
mkeyw 'Character-set',attchr ; Character set
mkeyw 'Date-Time',attdate ; Date and Time
mkeyw 'Length',attlen ; Length
mkeyw 'Type',atttype ; Type
mkeyw 'System-id',attsys ; System
comtab db 2 ; table of COM ports
mkeyw 'COM3',4 ; offset of COM3 address
mkeyw 'COM4',6 ; offset of COM4 address
cntltab db 2 ; SET CONTROL table
mkeyw 'Prefixed',0 ; 0 = send with prefix
mkeyw 'Unprefixed',1 ; 1 = send as-is
stsrtb db 11 ; Number of options
mkeyw 'Packet-length',srpack
mkeyw 'Padchar',srpad
mkeyw 'Padding',srnpd
mkeyw 'Pause',srpaus
mkeyw 'Start-of-packet',srsoh
mkeyw 'Quote',srquo
mkeyw 'End-of-packet',sreol
mkeyw 'Timeout',srtim
mkeyw 'Double-char',srdbl
mkeyw 'Ignore-char',srign
mkeyw 'Pathnames',srpath
ontab db 2
mkeyw 'off',0
mkeyw 'on',1
outputtab db 1 ; Set OUTPUT
mkeyw 'PACING',setopace
distab db 5 ; Set Display mode
mkeyw '7-bit',7 ; controls bit d8bit in flags.remflg
mkeyw '8-bit',8 ; sets d8bit
mkeyw 'Quiet',dquiet ; values defined in header file
mkeyw 'Regular',dregular
mkeyw 'Serial',dserial
distab2 db 3 ; for SET FILE DISPLAY
mkeyw 'Quiet',dquiet ; values defined in header file
mkeyw 'Regular',dregular
mkeyw 'Serial',dserial
fossiltab db 1 ; Fossil
mkeyw 'disable-on-close',1
; If abort when receiving files, can keep what we have or discard
abftab db 2
mkeyw 'Discard',1
mkeyw 'Keep',0
flotab db 5
mkeyw 'none',0
mkeyw 'xon/xoff',1+2 ; both directions
mkeyw 'incoming-xon/xoff',2
mkeyw 'outgoing-xon/xoff',1
mkeyw 'RTS/CTS',4
FIFOtab db 2
mkeyw 'FIFO-disabled',0
mkeyw 'FIFO-enabled',1
hndtab db 8
mkeyw 'none',0
mkeyw 'bell',bell
mkeyw 'cr',cr
mkeyw 'esc',escape
mkeyw 'lf',lf
mkeyw 'xoff',xoff
mkeyw 'xon',xon
mkeyw 'code',0ffh ; allow general numerial code
duptab db 2 ; SET DUPLEX table
mkeyw 'full',0
mkeyw 'half',1
partab db 6
mkeyw 'none',PARNON
mkeyw 'even',PAREVN
mkeyw 'odd',PARODD
mkeyw 'mark',PARMRK
mkeyw 'space',PARSPC
mkeyw 'HARDWARE',PARHARDWARE
parhwtab db 4 ; for 9-bit bytes
mkeyw 'even',PAREVNH
mkeyw 'odd',PARODDH
mkeyw 'mark',PARMRKH
mkeyw 'space',PARSPCH
exittab db 1 ; EXIT table
mkeyw 'warning',0
gettab db 3 ; GETOK dispatch table
mkeyw 'Yes',kssuc ; success = yes
mkeyw 'OK',kssuc ; ditto
mkeyw 'No',ksgen ; general failure
inptab db 5 ; Scripts. Set Input
mkeyw 'Case',inpcas ;[jrs]
mkeyw 'Default-timeout',inptmo ;[jrs]
mkeyw 'Echo',inpeco ;[jrs]
mkeyw 'Filter-echo',infilt
mkeyw 'Timeout-action',inpact ;[jrs]
resettab db 1
mkeyw 'Clock',80h
macrotab db 1 ; SET MACRO table
;; mkeyw 'Echo',0
mkeyw 'Error',1
taketab db 2 ; SET TAKE table
mkeyw 'Echo',0
mkeyw 'Error',1
xmitab db 4 ; SET TRANSMIT table
mkeyw 'Fill-empty-line',0
mkeyw 'Line-Feeds-sent',1
mkeyw 'Pause',3
mkeyw 'Prompt',2
debtab db 4 ; Set Debug command
mkeyw 'Off',0
mkeyw 'On',logpkt+logses
mkeyw 'Packets',logpkt
mkeyw 'Session',logses
logtab db 3 ; LOG command
mkeyw 'Packets',logpkt
mkeyw 'Session',logses
mkeyw 'Transactions',logtrn
srvdetab db 17 ; Server Enable/Disable list
mkeyw 'All',0fffh
mkeyw 'CD',cwdflg
mkeyw 'CWD',cwdflg
mkeyw 'Define',defflg
mkeyw 'Delete',delflg
mkeyw 'Dir',dirflg
mkeyw 'Finish',finflg
mkeyw 'Get',getsflg
mkeyw 'Host',hostflg
mkeyw 'Kermit',kerflg
mkeyw 'Login',pasflg
mkeyw 'Print',prtflg
mkeyw 'Retrieve',retflg
mkeyw 'Query',qryflg
mkeyw 'Send',sndflg
mkeyw 'Space',spcflg
mkeyw 'Type',typflg
trnstab db 2 ; Set Translation table
mkeyw 'Input',1
mkeyw 'Keyboard',2
ifndef no_tcp
tcptable db 14 ; Telnet or TCP/IP command
mkeyw 'address',1 ; local Internet address
mkeyw 'domain',2 ; local domain string
mkeyw 'broadcast',8 ; broadcast of all 0's or all 1's
mkeyw 'gateway',4 ; gateway address
mkeyw 'primary-nameserver',5 ; name servers
mkeyw 'secondary-nameserver',6
mkeyw 'subnetmask',3 ; our subnet mask
mkeyw 'host',7 ; host's IP name or IP number
mkeyw 'Packet-Driver-interrupt',9
mkeyw 'term-type',10 ; Options term type
mkeyw 'NewLine-mode',11 ; CR-NUL vs CRLF
mkeyw 'mode',13 ; NVT-ASCII or Binary
mkeyw 'mss',14 ; Max Segment Size
mkeyw 'debug-Options',12 ; debug Telnet Options
tcpmodetab db 2 ; TCP/IP Mode
mkeyw 'NVT-ASCII',0
mkeyw 'Binary',1
newlinetab db 3 ; TCP/IP Newline mode
mkeyw 'off',0
mkeyw 'on',1
mkeyw 'raw',2
domainbad db cr,lf,'?Bad domain name, use is such as my.domain.name$'
addressbad db cr,lf,'?string is too long$'
hostbad db cr,lf,'?Bad host, use IP name or IP number$'
tcpaddress db 'dhcp',(16-($-tcpaddress)) dup (0),0
tcpsubnet db '255.255.255.0',(16-($-tcpsubnet)) dup (0),0
tcpdomain db 'unknown',(32-($-tcpdomain)) dup (0),0
tcpgateway db 'unknown',(32-($-tcpgateway)) dup (0),0
tcpprimens db 'unknown',(16-($-tcpprimens)) dup (0),0
tcpsecondns db 'unknown',(16-($-tcpsecondns)) dup (0),0
tcphost db (60 -($-tcphost)) dup (0),0
tcpbcast db '255.255.255.255',(16-($-tcpbcast)) dup (0),0
tcpbtpserver db 17 dup (0) ; bootp server (response)
tcpport dw 23 ; TCP port
tcppdint dw 0 ; Packet Driver interrupt
tcpttbuf db 32 dup (0),0 ; term-type-override buffer
tcpnewline db 1 ; NewLine-Mode (default is on)
tcpdebug db 0 ; Options debugging (0 is off)
tcpmode db 0 ; NVT-ASCII is 0, Binary is 1
tcpmss dw 1460 ; MSS
endif ; no_tcp
; MACRO DATA STRUCTURES mcctab
mcclen equ macmax*10 ; length of mcctab
mcctab db 0 ; macro name table entries
db mcclen dup (0) ; room for macro structures
; END OF MACRO DATA STRUCTURES
ibmmac db 'IBM ' ; startup IBM macro definition + space
db 'set timer on,set parity mark,set local-echo on,'
db 'set handshake xon,set flow none,',0 ; asciiz
dialmac db '__DIAL ' ; "__DIAL "
db 'asg \%9 \v(carrier),set carr off,'
db 'output ATD\%1\%2\%3\%4\%5\%6\%7\%8\13,wait 90 CD,'
db 'asg \%8 \v(status),set carr \%9,end \%8,',0 ; asciiz
even
prmptr dw kerm ; pointer to prompt
tempptr dw 0 ; pointer into work buffer
domacptr dw 0 ; pointer to DO MAC string
min dw 0
max dw 0
numerr dw 0
numhlp dw 0
temp dw 0
temp1 dw 0 ; Temporary storage
temp2 dw 0 ; Temporary storage
askecho db 0 ; ask's echo control flag
deftemp dw 0
stkadr dw 0 ; non-zero if replacement keyboard xlator present
mccptr dw mcctab ; ptr to first free byte in mcctab
macptr dw 0 ; temp to hold segment of string
npages dw 10 ; # of pages of scrolling on each side
rollwidth dw 0 ; columns to roll back 80..207
portirq db 4 dup (0) ; user specified IRQ's for COM1..4
portfifo db 4 dup (1) ; user specified FIFO for COM1..4
takeerror db 0 ; Take Error (0 = off)
macroerror db 0 ; Macro Error (0 = off)
marray dw 27 dup (0) ; pointers to macro array mem areas
arraybad db cr,lf,'? Array size is too large, 32000 max$'
forstr1 db '_forinc ',0 ; append 'variable step'
forstr2 db ' if not > ',0 ; append 'variable end'
forstartptr dw 0
forendptr dw 0
forstepptr dw 0
forcmdsptr dw 0
forbadname db cr,lf,'?Not a variable name$'
data ends
data1 segment
askhlp1 db 'Variable name then prompt string$'
askhlp2 db 'Prompt string$'
askhlp3 db 'Enter a line of text$'
getokhlp db 'Optional prompt string$'
filhlp db ' Output filename for the log$'
forhlp db cr,lf,'FOR variable initial final increment'
db ' {command,command,...}$'
dishlp db cr,lf,' Quiet (no screen writing), Regular (normal),'
db ' Serial (non-formatted screen)'
db cr,lf,' and/or 7-BIT (default) or 8-BIT wide characters.$'
exitwhlp db cr,lf,' ON or OFF. Warn if sessions are active when exiting'
db ' Kermit$'
remhlp db cr,lf,' OFF to show file transfer display,'
db ' ON for quiet screen$'
macmsg db ' Specify macro name followed by body of macro, on same line$'
prmmsg db cr,lf
db ' Enter new prompt string or press Enter to regain default prompt.'
db cr,lf,' Use \fchar(123) notation for special chars;'
db ' Escape is \fchar(27).$'
rspathhlp db cr,lf,' ON retains pathnames during file transfer,'
db ' OFF removes them$'
srxhlp1 db cr,lf,' Enter code for received byte code for'
db ' local byte ',cr,lf,' use ascii characters themselves or'
db cr,lf,' numerical equivalents of \nnn decimal'
db ' or \Onnn octal or \Xnnn hexadecimal',cr,lf
db ' or keywords ON or OFF (translation is initially off)'
db cr,lf,'$'
takchlp db cr,lf,'Value 0 to 65535 for COUNT in script IF COUNT command$'
nummsg1 db cr,lf,'?Use a number between $'
nummsg2 db ' and $'
srvthlp db 'seconds, 0-255, waiting for a transaction$'
unkchhlp db cr,lf,' Disposition of files arriving with unknown'
db ' character sets:',cr,lf,' Keep (default), Cancel$'
winhelp db cr,lf,'Number of sliding window slots 1 (no windowing) to 32$'
eophlp db ' Decimal number between 0 and 31$'
ctlhlp db ' Decimal number between 0 and 31, 128 and 159$'
cntlhlp db cr,lf,' PREFIXED <0..31, 128..159> protectively quotes this'
db ' control code',cr,lf
db ' UNPREFIXED <0..31, 128..159> sends control code as-is'
db cr,lf,' Use ALL to change all codes at once.$'
sohhlp db ' Decimal number between 0 and 31.',cr,lf,' Special case:'
db ' up to 126, but reduces strength of the protocol.$'
dmphlp db ' Filename to hold screen dumps$'
prnhlp db ' Filename for printer output (default is PRN)$'
prnerr db cr,lf,' Cannot open that name. Using default of PRN$'
erlhlp db ' Decimal number between 0 and 255$'
pakerr db cr,lf,'?Choose a decimal number '
db 'from 20 to 94 (normal) or to 9024 (long)$'
pakhlp db cr,lf,'Decimal number between 20 and 94 (normal) or '
db '9024 (long)$'
padhlp db cr,lf,' Decimal number between 0 and 31 or 127$'
pauhlp db ' Decimal number between 0 and 65383 milliseconds$'
quohlp db ' Decimal number between 33 and 126$'
retryhlp db ' Decimal number between 1 and 63$'
rollhlp db ' Decimal number between 0 and 8000$'
dblhlp db ' Decimal number between 0 and 255$'
stophlp db ' Serial port stop bits, 1 (default) or 2$'
luserh db cr,lf,'Username Password from remote Kermit (0-16 chars each)$'
lpassh db cr,lf,'Password from remote Kermit (0-16 chars,'
db ' spaces allowed)$'
prefhlp db cr,lf,' single char (def is ~) or number between 33-62 or'
db ' 96-126$'
timhlp db ' Decimal number between 0 and 94$'
delyhlp db ' Delay seconds before sending file (0-63)$'
eschlp db cr,lf,'Press literal control keys (ex: Control ]) or'
db ' enter in \nnn numerical form$'
hnd1hlp db cr,lf,'XON (\17), XOFF (\19), CR (\13), LF (\10), BELL (\7),'
DB ' ESC (\27), NONE (\0)'
db cr,lf,' or "CODE" followed by decimal number$'
intoms db 'number of seconds to wait before timeout',cr,lf,'$'
loghlp db cr,lf
db ' PACKETS - during file transfers (to default file PACKET.LOG)'
db cr,lf
db ' SESSION - during Connect mode (to default file SESSION.LOG)'
db cr,lf
db ' TRANSACTIONS - files transfers (to default file TRANSACT.LOG)'
db cr,lf,' followed by an optional filename for the log and'
db ' optional',cr,lf,' '
loghlp2 db ' APPEND (default) or NEW$'
carhlp db cr,lf,' ON or OFF. Sense modem Carrier Detect and end'
db ' connection if it drops.$'
comhlp db cr,lf,' Set port address, IRQ, and control UART FIFO.'
db cr,lf,' Address of the COM1 - COM4 port (ex: COM3 \x02f8 or'
db ' COM4 \x02e8)$'
irqhlp db cr,lf,' IRQ of port (ex: \3)$'
fifohlp db cr,lf,' FIFO-disable or FIFO-enable or press Enter key.'
db cr,lf,' FIFO-disable means bypass UART buffer$'
debhlp db cr,lf,' PACKETS - during file transfers' ; Debugging
db cr,lf,' SESSION - during Connect mode'
db cr,lf,' ON - both packets and session'
db cr,lf,' OFF - turns off all debugging$'
dialhlp db ' Phone number to dial$'
dohlp db cr,lf,'definitions of variables (\%n), or press ENTER key$'
fossilhlp db cr,lf,' OFF to leave Fossil active (default), ON to disable'
db ' when done with port$'
sdshlp db cr,lf,'DISABLE or ENABLE access to selected Server commands:'
db cr,lf
db ' CD/CWD, DEFINE, DEL, DIR, FINISH (includes BYE & LOGOUT),'
db ' GET, HOST,',cr,lf
db ' KERMIT, LOGIN, PRINT, QUERY, RETRIEVE, SEND, SPACE, TYPE,'
db ' and ALL.$'
xfchhlp db cr,lf,' Which character set to put on the wire during file'
db ' transfers:',cr,lf
db ' TRANSPARENT (regular PC codes)',cr,lf
db ' LATIN1 (ISO 8859-1)',cr,lf
db ' LATIN2 (ISO 8859-2)',cr,lf
db ' HEBREW (ISO 8859-8)',cr,lf
db ' CYRILLIC (ISO 8859-5)',cr,lf
db ' JAPANESE-EUC$'
xferhlp1 db cr,lf,' OFF: disable feature, ON: enable (default), FORCE:'
db ' forced on$'
xfchhlp2 db cr,lf,' READABLE: translate some/many characters to/from'
db ' locally readable form (def).'
db cr,lf,' INVERTIBLE: use codes which can be copied back to the'
db ' host in its form.$'
xferhlp3 db cr,lf,'Automatic (Binary mode between like systems),'
db ' manual (default)$'
xfilhlp db 'NONE, SPACE, or filler character$'
xpmthlp db 'Host echo char acting as prompt, \1-\255$'
xpauhlp db 'Millisec to pause between lines, 1 - 65000$'
opacehlp db 'Millisec to pause between OUTPUT bytes, 0 - 65000$'
pophlp db 'Status value to be returned msg, nothing if no new value$'
sethlp db cr,lf
db ' Alarm sec from now or HH:MM:SS '
db ' Local-echo on/off '
db cr,lf
db ' Attributes packets on/off '
db ' Mode-line on/off'
db cr,lf
db ' Bell on/off at end of xfers '
db ' NetBios-name (our local name)'
db cr,lf
db ' Block-check-type checksum/CRC '
db ' Output pacing (ms between bytes) '
db cr,lf
db ' Carrier sense modem Carrier Detect'
db ' Parity even/odd/mark/space/none'
db cr,lf
db ' COM1 - COM4 port-address irq '
db ' Port (or Line) 1/2/COM1/COM2/etc'
db cr,lf
db ' Control prefixed/unprefixed code '
db ' Printer filespec for Connect mode'
db cr,lf
db ' Count number a loop counter '
db ' Prompt string (new Kermit prompt)'
db cr,lf
db ' Debug on/off display packets '
db ' Receive parameter many things'
db cr,lf
db ' Default-disk '
db ' Repeat Counts (on/off) '
db cr,lf
db ' Delay secs before Sending file '
db ' Retry limit for packet send/receive'
db cr,lf
db ' Destination Disk/Screen/Printer '
db ' Rollback, terminal screens'
db cr,lf
db ' Display quiet/reg/serial show cnts?'
db ' Send parameter many things'
db cr,lf
db ' Dump filespec screen to disk '
db ' Server parameter'
db cr,lf
db ' Duplex half or full '
db ' Speed or Baud many speeds'
db cr,lf
db ' EOF Ctrl-Z/NoCtrl-Z ^Z ends file? '
db ' Stop-bits always 1'
db cr,lf
db ' End-of-line char cr or whatever '
db ' Take Echo or Error on/off'
db cr,lf
db ' Errorlevel number for DOS Batch '
db ' Telnet address,mask,nameserver etc'
db cr,lf
db ' Escape-char ^] or whatever '
db ' Terminal type and parameters'
db cr,lf
db ' Exit warning (if session active) '
db ' Timer on/off time packet waiting'
db cr,lf
db ' File (Character-set, Type, Warning)'
db ' Translation IN Connect mode rcv''d char'
db cr,lf
db ' Flow-control none xon/xoff rts/cts'
db ' Transfer Character-set (on wire) '
db cr,lf
db ' Handshake xon/xoff/cr/lf/bell/esc..'
db ' Transmit parameters, for scripts'
db cr,lf
db ' Incomplete file keep/discard '
db ' Unknown-character-set (keep/cancel)'
db cr,lf
db ' Input timeout, etc (for scripts) '
db ' Warning on/off if file renamed'
db cr,lf
db ' Key key-ident definition '
db ' Windows number of sliding window slots'
db '$'
ifndef no_tcp
hosthlp db cr,lf,'Internet name or number (ddd.ddd.ddd.ddd) of '
db 'the remote machine$'
domainhlp db cr,lf,'Name of your domain$'
subnethlp db cr,lf,'Subnetmask, decimal ddd.ddd.ddd.ddd$'
addrhelp db cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd, of this'
db ' machine or'
db cr,lf,' BOOTP, DHCP, RARP, or Telebit-PPP$'
iphelp db cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd$'
tcppdinthlp db cr,lf,'Interrupt on PC for Packet Driver, \x60 to \x7f'
db ' or use 0 for automatic search,'
db cr,lf,' or ODI to use Novell''s ODI interface$'
tcpttyhlp db cr,lf,' Telnet Options terminal identification override '
db 'string.'
db cr,lf,' This does NOT modify the real terminal type.'
db ' Press ENTER to remove this',cr,lf
db ' override and report the real terminal type.$'
tcpnlhlp db cr,lf,' ON sends CR LF for each CR, OFF sends CR NUL,'
db ' RAW sends just CR$'
tcpmsshlp db cr,lf,' Maximum Segment Size, 16 to 1460 bytes$'
endif ; no_tcp
arrayhlp db ' \&<char>[size] size of 0 undefines the array$'
data1 ends
code1 segment
extrn makebuf:far, domath:far, strlen:far, strcpy:far
extrn prtasz:far, decout:far, strcat:far, toupr:far
extrn isfile:far, malloc:far, dec2di:far, takrd:far
assume cs:code1
code1 ends
code segment
extrn comnd:near, baudst:near, prompt:near, coms:near, cwdir:near
extrn lnout:near, breakcmd:near
extrn vts:near, setalrm:near, serrst:near
extrn prnopen:near, pntflsh:near
ifndef no_network
extrn setnbios:near ; in MSXIBM, needs stub for other machines
endif ; no_network
assume cs:code, ds:data, es:nothing
; DO defined macro command
; DO macname variable variable also defines variables \%1, \%2, ...\%9
DOCOM PROC NEAR
mov dx,offset mcctab ; table of macro defs
xor bx,bx ; help is table
mov ah,cmkey ; get key word (macro name)
call comnd ; get pointer to keyword structure
jnc docom1 ; nc = success, bx = 16 bit data
ret ; failure
DOCOM1: mov domacptr,bx ; segment of definition string
mov comand.cmquiet,0 ; permit command echoing
mov bx,offset decbuf+2 ; point to borrowed work buffer
docom1a:mov dx,offset dohlp ; help
mov comand.cmblen,decbuflen ; length of analysis buffer
mov comand.cmdonum,1 ; \number conversion allowed
mov ah,cmword
call comnd
jnc docom1b
ret
docom1b:mov si,bx ; terminating null
sub si,ax ; minus length
mov [si-2],ax ; store length in preceeding word
add bx,2 ; leave a full word empty
mov word ptr [bx-2],0
or ax,ax ; any text?
jnz docom1a ; nz = got text, get more
mov ah,cmline ; read and discard rest of line
mov bx,offset rdbuf ; discard here
xor dx,dx ; no help
call comnd
jnc docom2 ; nc = success
ret
docom2: inc taklev ; prepare for being in Take below
call hidemac ; hide previous \%0..\%9 macros
dec taklev
call getname ; get name of this macro to rdbuf
mov cx,word ptr rdbuf ; length of "\%0 plus found name"
call dodecom ; define macro \%0 as macro name
jc docomx ; c = failure
push es
mov ax,domacptr ; macro definition string segment
mov es,ax ; string is in es:si
xor si,si ; point to count word
call docnv ; convert macro string in-place
pop es ; to lift top {} and do bare "," -> CR
jc docomx ; c = failure
mov max,1 ; temp for counting 1 + number args
mov word ptr rdbuf+4,' 1' ; number of first variable
docom3: mov word ptr rdbuf,0 ; clear length field, install \%x name
mov word ptr rdbuf+2,'%\' ; start with '\%1 '
mov word ptr rdbuf+6,0 ; clear text field
mov tempptr,offset rdbuf+6 ; pointer to location of found word
xor ch,ch ; make cx = 1 - 9
mov cl,rdbuf+4 ; cx = word # of interest, for getwrd
sub cl,'0' ; remove ascii bias
mov si,offset decbuf+2 ; source = work buffer (borrowed)
call getwrd ; get CX-th word from work buf (1-9)
cmp deftemp,0 ; length of word, was it found?
je docom4 ; e = no, end variable definition part
add deftemp,4 ; count '\%n ' in command line length
inc max ; one more argument
mov cx,deftemp ; command length for dodecom
call dodecom ; add keyword+def using DEF MAC below
jc docomx ; c = failure
inc rdbuf+4 ; inc number of variable in '\%n '
cmp rdbuf+4,'9'
jbe docom3 ; do '1' through '9', if available
docom4: call takopen_macro ; create the DO the macro itself
jc docomx ; c = failure
mov bx,takadr ; point to current structure
push es
mov es,domacptr ; segment of macro definition string
mov [bx].takbuf,es ; remember in Take structure
mov cx,es:word ptr[0] ; length of definition string
mov si,cx
cmp byte ptr es:[si+2-1],CR ; terminates in CR?
je docom5 ; e = yes
mov byte ptr es:[si+2],CR ; force CR termination
; keeps open macro until after last command has executed, for \%digit
inc cx ; add CR to macro length
mov es:[0],cx ; update image too
docom5: pop es
mov [bx].takcnt,cx ; # of unread chars in buffer
mov cx,max ; 1 + number of arguments
mov [bx].takargc,cx
mov al,taklev ; Take level now
mov [bx].takinvoke,al ; remember take level of this DO
clc ; success
ret
docomx: inc taklev ; simulate Take closing
call unhidemac ; recover hidden variables
dec taklev
stc ; say failure
ret
DOCOM ENDP
; Extract CX-th word (cx = 1-9) from buffer (SI). Enter with si = source
; string and tempptr pointing at destination. Returns deftemp (count) of
; transferred characters.
; All registers preserved.
getwrd proc near
push si
push di
push es
push cx ; save word counter (1-9)
getwr1: mov ax,[si-2] ; get length of word
or ax,ax
jz getwr2 ; z = zero length, no word, quit
dec cx ; one less word
or cx,cx
jz getwr2 ; z = at desired word
add si,ax ; step to next word (<cnt><text>)
add si,2 ; point to text
jmp short getwr1
getwr2: mov deftemp,ax ; returned length of word
mov cx,ax ; length of word
mov di,tempptr ; where to store word/string
push ds
pop es ; set es to data segment
cld
rep movsb ; copy bytes to destination
xor al,al
stosb ; force null terminator
pop cx
pop es
pop di
pop si
ret
getwrd endp
; Get macro name, given the action pointer in domacptr.
; Return rdbuf as word:length that follows, then "\%0 macro-name"
getname proc near
push bx
push cx
push dx
push si
push di
mov dx,domacptr ; action word to be matched
mov bx,offset mcctab+1 ; table of macro names, skip count
mov word ptr rdbuf,4 ; name length and space
mov word ptr rdbuf+2,'%\' ; define '\%0 '
mov word ptr rdbuf+4,' 0'
mov cl,mcctab ; number of entries
xor ch,ch
jcxz getnam3 ; z = empty table
getnam1:push cx
mov cx,[bx] ; length of name
mov si,bx ; point at structure member
add si,2 ; plus count
add si,cx ; plus length of name
mov ax,[si] ; get action word
cmp ax,dx ; correct action word?
jne getnam2 ; ne = no
push es
push ds
pop es
add word ptr rdbuf,cx ; length of macro \%0 + name
mov di,offset rdbuf+6 ; where to store text
mov si,bx
add si,2 ; source of text
cld
rep movsb ; copy name to rdbuf+6
mov byte ptr [di],0 ; null terminator
pop es
pop cx
jmp short getnam3 ; exit
getnam2:mov ax,[bx] ; get length of name
add ax,4 ; plus count and word pointer
add bx,ax ; point to next entry
pop cx
loop getnam1 ; look at next entry
getnam3:pop di
pop si
pop dx
pop cx
pop bx
ret
getname endp
; Local macro macro macro...
; Hides existing macros of those names, if any
localmac proc near
cmp taklev,0 ; in a take file/macro?
je localmx ; e = no, quit
mov bx,offset rdbuf+2
xor dx,dx ; help
mov comand.cmper,1 ; don't expand macro
mov ah,cmword ; get name of macro
call comnd
jnc localm1
localmx:mov ah,cmeol ; get eol
call comnd
ret
localm1:mov word ptr rdbuf,ax ; save name length
or ax,ax ; empty (end of command)?
jz localmx ; z = yes, quit
mov bx,offset mcctab+1 ; table of macro names, skip count
xor ch,ch
mov cl,mcctab ; number of entries
jcxz localmx ; z = empty table
localm2:mov ax,word ptr rdbuf ; get user macro name length
cmp word ptr [bx],ax ; name length, same?
jne localm4 ; ne = no, get next table entry
push cx ; compare names
push si
push di
mov cx,ax ; length of macro (either)
mov si,offset rdbuf+2 ; user word
mov di,bx ; table word length
add di,2 ; table word
localm3:mov al,[si]
mov ah,[di]
inc si
inc di
call toupr ; upper case both
cmp al,ah ; same?
loope localm3 ; e = yes
je short localm5 ; e = fully matched
pop di
pop si
pop cx
localm4:mov ax,[bx] ; get length of name
add ax,4 ; plus count and word pointer
add bx,ax ; point to next entry
loop localm2 ; look at next table entry
jmp localmac ; get next macro name
localm5:pop di
pop si
pop cx
call hidewrk ; hide macro pointed to by bx
jmp localmac ; get next macro name
localmac endp
; DEFINE and ASSIGN macro commands
; Data structures comments. Macro name is stored in table mcctab as if we
; had used macro mkeyw, such as mkeyw 'mymac',offset my_definition.
; In detail: dw length of name
; db 'name'
; dw segment:0 of definition string
; Mcctab begins with a byte holding the number of macros in the table; one,
; IBM, is established at assembly time. Mcctab is 10*macmax bytes long.
; Pointer mccptr holds the offset of the next free byte in mcctab.
; Definition strings are stored in individually allocated memory as
; dw length of definition string below
; db 'definition string'
; A new definition is read into buffer rdbuf+2, where word rdbuf is reserved
; to hold the length of the macro's name during intermediate processing.
; If the definition is absent then the macro is removed from the tables.
;
; ASSIGN is equivalent to DEFINE, except in the definition string substitution
; variable names are expanded to their definitions.
; DEFINE does not expand substitution variables.
; Both commands will remove a first level curly brace pair if, and only if,
; the definition begins and ends with them (trailing whitespace is allowed).
; HIDE_ASSIGN and HIDE_DEFINE are like ASSIGN and DEFINE except the
; destination name is expanded for substitution variables.
;
HIDE_ASSIGN proc near
mov defkind,2 ; flag command as ASSIGN, vs DEFINE
jmp short dodefcom ; common code
HIDE_ASSIGN endp
HIDE_DEFINE proc near
mov defkind,3 ; flag command as DEFINE, vs ASSIGN
jmp short dodefcom ; common code
HIDE_DEFINE endp
ASSIGN PROC NEAR
mov defkind,0 ; flag command as ASSIGN, vs DEFINE
jmp short dodefcom ; common code
ASSIGN ENDP
UNDEFINE PROC NEAR ; undefine variable or array
mov defkind,4 ; bit 4 means undefine
jmp short dodefcom
UNDEFINE ENDP
DODEF PROC NEAR
mov defkind,1 ; flag command as DEFINE, vs ASSIGN
DODEFCOM:
test defkind,2 ; HIDE_assign/define?
jnz dodef0 ; nz = yes, expand destination
mov comand.cmper,1 ; do not react to '\%' in macro name
dodef0: mov ah,cmword
mov bx,offset rdbuf+2 ; buffer for macro name
mov word ptr rdbuf,0
mov comand.cmarray,1 ; allow sub in [..] of \&<char> arrays
mov comand.cmblen,length rdbuf-2 ; length of analysis buffer
mov dx,offset macmsg
call comnd ; get macro name
jnc dodef1 ; nc = success
ret ; failure
dodef1: or ax,ax ; null entry?
jnz dodef2 ; nz = no
mov dx,offset ermes6 ; more parameters needed
jmp reterr
dodef2: mov bx,offset rdbuf+2 ; start of string
cmp word ptr [bx],'%\' ; \%<char> substitution variable?
jne dodef2b ; ne = no
cmp ax,2 ; count, but missing <char>?
ja dodef2a ; a = no
mov byte ptr [bx+2],'_' ; slip in an underscore
dodef2a:mov ax,3 ; limit to \%<char>, one char name
dodef2b:test defkind,4 ; UNDEFINE?
jz dodef2c ; z = no
add bx,ax ; string length
mov word ptr [bx],0 ; create double null for defarray
mov comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
mov ah,cmeol ; get eol, no definition string
call comnd
jnc dodef3 ; nc = success
ret
dodef2c:add bx,ax ; point to string terminator
mov byte ptr [bx],' ' ; replace null with space separator
inc bx ; where definition will start
mov ax,cmdblen ; length of rdbuf
sub ax,2 ; skip initial count word
add ax,bx ; next byte goes to bx
sub ax,offset rdbuf+2 ; amount of cmd line used
mov comand.cmblen,ax ; our new buffer length
mov al,defkind ; get ASSIGN/DEFINE flag
and al,1 ; pick out source flag bit
mov comand.cmper,al ; react (ASSIGN) to '\%' in definition
mov comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
mov ah,cmline ; get a line of text
mov dx,offset macmsg ; help, bx is buffer offset
call comnd ; get macro definition text
jnc dodef3 ; nc = success
ret ; failure
dodef3: mov dx,offset rdbuf+2
call strlen ; length to cx
jmp short dodecom
DODEF ENDP
; Make a macro table entry and allocate buffer space.
; Enter with rdbuf+2 et seq = <macro name><spaces><arg><spaces><arg> ...
; and CX = byte count of line, starting at rdbuf+2.
; Word rdbuf+0 computed here as length of keyword.
; Allocates memory based on analyzed size of command line, returns memory
; segment in macptr and in AX. Returns carry set if failure.
DODECOM PROC NEAR
cmp word ptr rdbuf+2,'&\' ; dealing with arrays?
jne dode1 ; ne = no
call defarray ; yes, do it in segment code1
ret
dode1: push si ; macro name in rdbuf+2 et seq
push di ; cmd line length in deftemp
push es
push ds ; address data segment
pop es
push deftemp
mov deftemp,cx ; cmd line len, cx = running counter
mov rdbuf,0 ; number of chars in keyword so far
; uppercase the keyword, look for end
mov si,offset rdbuf+2 ; point at macro name itself
xor dx,dx ; a counter
cld ; strings go forward
dode2: lodsb ; get a byte
cmp al,'a' ; map lower case to upper
jb dode3
cmp al,'z'
ja dode3
sub al,'a'-'A'
mov [si-1],al ; uppercase if necessary
dode3: inc dx ; increment char count of keyword
cmp al,' ' ; is this the break character?
loopne dode2 ; no, loop thru rest of word
jne dode4 ; ne = did not end with break char
dec dx ; yes, don't count in length
dode4: mov di,offset rdbuf ; point at mac name length
mov [di],dx ; insert length in rdbuf
push dx ; save length around call
call remtab ; remove any duplicate keyword
; check for free space for keyword
pop ax ; keyword text length
add ax,4 ; plus count and word pointer
add ax,mccptr ; add to free space pointer
cmp ax,offset mcctab+mcclen ; enough room for name?
jb dode5 ; b = yes
mov dx,offset ermes1 ; too many macro names
pop deftemp
pop es
pop di
pop si
jmp reterr
; should be looking one byte after
; space break char between name
; and definition
dode5: mov dx,si ; definition string
call strlen ; get new length into cx
jcxz dode5c ; z = no definition, exit this routine
dode5a: mov al,[si] ; read a definition byte
cmp al,',' ; leading COMMA?
je dode5b ; e = yes, from {,cmd,cmd} stuff
cmp al,CR ; leading CR?
je dode5b ; e = yes, skip over it
cmp al,' ' ; leading space?
jne dode6 ; ne = no, have reached def text
dode5b: inc si ; inc pointer, count down qty
loop dode5a ; look again (note cx > 0 check above)
dode5c: pop deftemp ; exit point with no definition left
pop es
pop di
pop si
clc
ret
dode6: mov deftemp,cx ; remember definition length here
; install new keyword
jcxz dode10 ; z = no def (should not happen here)
mov ax,cx ; memory needed
add ax,2+1+1 ; plus count word and CR and saftey
call malloc
jc dode12 ; c = error, not enough memory
dode7: mov macptr,ax ; store new segment
mov es,ax ; segment of string
xor di,di ; offset of count word
mov cx,deftemp ; length of definition string
mov ax,cx
cld
stosw ; store length of string
rep movsb ; copy string
mov bx,offset mcctab
mov dx,offset rdbuf ; count word + name string
call addtab
dode10: mov ax,macptr ; return buffer segment to caller
pop deftemp
pop es
pop di
pop si
clc ; success
ret
dode12: pop deftemp ; no memory, clean stack
pop es
pop di
pop si
mov dx,offset ermes2 ; no room for definition
mov ah,prstr
int dos
stc
ret
DODECOM ENDP
DECLARE proc near ; declare array \&<char @a..z>[size]
mov comand.cmper,1 ; do not react to '\&' in macro name
mov comand.cmdonum,1 ; \number conversion allowed
mov comand.cmarray,1 ; allow sub in [..]
mov ah,cmline
mov bx,offset rdbuf+2 ; buffer for macro name
mov comand.cmblen,length rdbuf-2 ; length of analysis buffer
mov dx,offset arrayhlp
call comnd ; get macro name
jnc ndecl1 ; nc = success
ret ; failure
ndecl1: call fdeclare ; call the far version
ret
DECLARE endp
; ASK <variable or macro name> <prompt string>
; Defines indicated variable/macro with text from user at keyboard or pipe
; (but not from a Take/macro). Prompt string is required.
; ASKQ does the same, but does not echo user's response.
ASKQ PROC NEAR
mov askecho,1 ; temp to flag as Quiet version
mov temp,0
jmp short ask0 ; do common code
ASKQ ENDP
GETC PROC NEAR
mov askecho,1
mov temp,1 ; signal as getc
jmp short ask0 ; do common code
GETC ENDP
ASK PROC NEAR
mov askecho,0 ; temp to flag as echoing version
mov temp,0
ask0: ; common code for ASK and ASKQ
mov bx,offset decbuf+2 ; point to work buffer
mov word ptr decbuf,0
mov dx,offset askhlp1 ; help
mov comand.cmper,1 ; do not expand variable name
mov comand.cmarray,1 ; allow sub in [..] of \&<char> arrays
mov ah,cmword ; get variable name
call comnd
jnc ask1 ; nc = success
ret ; failure
ask1: or ax,ax ; anything given?
jnz ask2 ; nz = yes
mov dx,offset ermes6 ; more parameters needed
jmp reterr
ask2: cmp word ptr decbuf+2,'%\' ; \%<char> substitution variable?
jne ask2b ; ne = no
cmp ax,2 ; but missing <char>
ja ask2a ; a = no
mov decbuf+4,'_' ; slip in an underscore
ask2a: mov ax,3 ; limit to a single char
ask2b: mov bx,offset decbuf+2 ; start of name
add bx,ax ; plus length of variable name
mov word ptr [bx],0+' ' ; put space+NULL separator after name
; get ASK command prompt string
mov bx,offset decbuf+129 ; borrowed buffer for prompt
mov dx,offset askhlp2
mov comand.cmblen,127 ; our buffer length
sub comand.cmblen,ax ; minus part used above
mov comand.cmdonum,1 ; \number conversion allowed
mov comand.cmcr,1 ; bare cr's allowed (empty prompt)
mov ah,cmline ; get prompt string
call comnd
jnc ask3 ; nc = success
ret ; failure
ask3: push ax
mov ah,cmeol
call comnd
pop ax
jnc ask4
ret
or ax,ax ; anything given?
jnz ask4 ; nz = yes
mov dx,offset ermes6 ; more parameters needed
jmp reterr
ask4: mov bx,offset decbuf+129
add bx,ax
mov word ptr [bx],0020h ; printing terminator for prompt
mov comand.cmdirect,1 ; say read directly from kbd/file
mov dx,offset decbuf+129 ; converted prompt string, asciiz
call prompt ; use our prompt
mov bx,offset rdbuf+129 ; use this buffer for raw user input
mov word ptr [bx],0 ; insert terminator
mov dl,askecho ; get echo/quiet flag
mov comand.cmquiet,dl ; 0 if echoing
mov dx,offset askhlp3 ; help for user input
mov comand.cmdirect,1 ; say read directly from kbd/file
cmp temp,1 ; getc?
jne ask8 ; ne = no
ask5: mov dl,0ffh
mov ah,dconio ; read console
int dos
jz ask5 ; z = nothing there
cmp al,3 ; Control-C?
jne ask6 ; ne = no
mov flags.cxzflg,'C' ; return Control-C status to parser
stc ; return error
ret
ask6: or al,al ; scan code being returned?
jnz ask7 ; nz = no, accept
mov ah,dconio ; read and discard second byte
mov dl,0ffh
int dos
mov ah,conout ; ring the bell
mov dl,bell
int dos
jmp short ask5 ; else unknown, ignore
ask7: xor ah,ah ; null terminator
cmp al,'(' ; function delimiters?
je ask7a ; e = yes
cmp al,')'
je ask7a ; e = yes
cmp al,'{' ; string delimiters?
je ask7a ; e = yes
cmp al,'}'
je ask7a ; e = yes
cmp al,DEL ; this control?
je ask7a ; e = yes
cmp al,' ' ; senstive (controls + space)?
ja ask7b ; a = no
ask7a: mov rdbuf+129,'\' ; numeric form prefix
mov di,offset rdbuf+130
call dec2di ; convert to \decimal, asciiz
clc
jmp short ask9
ask7b: mov word ptr rdbuf+129,ax ; byte and terminator
clc
jmp short ask9 ; process byte
ask8: mov ah,cmline ; read user's input string
mov comand.cmper,1 ; do not expand variable names
mov comand.cmdonum,1 ; \number conversion allowed
call comnd
ask9: mov comand.cmquiet,0 ; permit echoing again
mov comand.cmdirect,0 ; read normally again
jnc ask10 ; nc = success
ret ; Control-C, quit now
ask10: mov cx,ax ; length of entry
mov di,offset rdbuf+2
mov si,offset decbuf+2
call strcpy
mov dx,di
call strlen
add di,cx
mov si,offset rdbuf+129
call strcpy
mov dx,offset rdbuf+2 ; command buffer beginning
call strlen ; CX=len of <variable>< ><user string>
call DODECOM ; define the macro/variable and exit
ret
ASK ENDP
; GETOK <prompt> displays prompt or default prompt, asks for affirmative
; user reply, returns success/fail status.
getok proc near
mov bx,offset rdbuf ; point to work buffer
mov dx,offset getokhlp
mov comand.cmblen,127 ; our buffer length
mov comand.cmcr,1 ; bare cr is ok
mov comand.cmdonum,1 ; \number conversion allowed
mov ah,cmline ; get prompt string
mov comand.cmcr,0
call comnd
jnc getok1 ; nc = success
ret ; failure
getok1: or ax,ax ; anything given?
jnz getok2 ; nz = yes
mov si,offset getdef ; default prompt
mov di,offset rdbuf
call strcpy ; paste in default prompt
getok2: mov si,offset rdbuf
mov dx,si
call strlen ; get length to cx
mov bx,cx
mov word ptr [si+bx],0020h ; printing terminator for prompt
getok3: mov dx,offset rdbuf ; converted prompt string, asciiz
mov comand.cmdirect,1 ; force input from kbd/file
call prompt ; use our prompt
mov flags.cxzflg,0 ; clear Control-C indicator
mov dx,offset gettab ; use this table
xor bx,bx ; table is help
mov comand.cmcr,1 ; null response permitted
mov ah,cmkey ; read user's input word
call comnd
mov comand.cmcr,0
mov comand.cmdirect,0 ; end force input from kbd/file
jnc getok4 ; nc = success
cmp flags.cxzflg,'C' ; did user type Control-C to quit?
jne short getok3 ; ne = no, syntax failure, reprompt
stc ; set carry flag again
jmp short getok5 ; exit failure
getok4: push bx
mov comand.cmdirect,1 ; force input from kbd/file
mov ah,cmeol ; get c/r confirmation
call comnd
mov comand.cmdirect,0 ; end force input from kbd/file
pop bx ; recover keyword 16 bit value
getok5: jnc getok6 ; nc = success
mov kstatus,ksgen ; failure
ret ; Control-C, quit now
getok6: mov kstatus,bx ; return status
ret
getok endp
; FOR macro-name start end step {commands}
FORCMD proc near
mov kstatus,ksgen ; general command failure
mov ah,cmword ; macro name
mov bx,offset decbuf
mov dx,offset forhlp ; help
mov comand.cmper,1 ; don't react to \%x variables
call comnd
jnc for1 ; nc = success
forx: mov ah,cmeol ; consume and discard the rest
call comnd
stc
ret ; failure
for1: cmp word ptr decbuf,'%\' ; start of variable name?
jne for2 ; ne = no
cmp ax,3 ; only three chars in name?
je for3 ; e = yes, we have \%<char>
for2: mov dx,offset forbadname
mov ah,prstr
int dos
jmp short forx
for3: mov bx,offset decbuf+4 ; where 'start' begins
mov forstartptr,bx ; remember where 'start' begins
mov dx,offset forhlp
mov ah,cmword ; get 'start'
call comnd
jc forx ; c = failure
mov bx,forstartptr ; 'start'
call todigits ; convert to string of digits
mov dx,offset forhlp
jc forx ; c = failure
inc bx ; leave null terminator intact
mov forendptr,bx ; 'end' starts here
mov dx,offset forhlp
mov ah,cmword ; get 'end'
call comnd
jc forx ; c = failure
mov bx,forendptr ; 'end' string
call todigits ; convert to string of digits
jc forx ; c = failure
inc bx ; leave null terminator intact
mov forstepptr,bx ; 'step' starts here
mov dx,offset forhlp
mov ah,cmword ; get 'step'
call comnd
jc forx ; c = failure
mov bx,forstepptr
mov cl,[bx] ; get possible minus sign on step
mov byte ptr temp,cl ; save for bottom of this work
call todigits ; convert to string of digits
jc forx ; c = failure
inc bx ; leave null terminator intact
mov forcmdsptr,bx ; commands start here
mov dx,offset forhlp
mov comand.cmper,1 ; don't react to \%x variables
mov comand.cmblen,cmdblen ; allow long lines
mov comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
mov ah,cmline ; get {commands}
call comnd
jc forx ; c = failure
; At this point decbuf looks like this:
; <string variable name><byte null><string end><byte null>
; <string step><byte null><string commands><byte null>
for4: ; define variable<space><start>
mov si,offset decbuf ; start of variable name
mov di,offset rdbuf+2
call strcpy ; variable name
mov dx,di
call strlen ; length to cx for dodecom
add di,cx
mov byte ptr [di],' ' ; space
inc di ; look at next byte
push di ; where number is formed
mov si,forstartptr
call strcpy ; copy start
mov dx,di
call strlen
add dx,cx ; point at terminating null
mov di,dx
mov word ptr [di],'-' ; minus, null
mov si,forstepptr ; step
call strcat ; append, have (start - step)
pop di
mov dx,di
mov domath_ptr,dx
call strlen
mov domath_cnt,cx
call domath ; math to dx:ax
push word ptr decbuf
push word ptr decbuf+2 ; preserve variable name \%c
call lnout ; DX:AX to DS:DI as ASCII digits
pop word ptr decbuf+2 ; retore variable around work
pop word ptr decbuf
mov dx,offset rdbuf+2 ; buffer for dodecom
call strlen ; length to cx for dodecom
call dodecom ; define macro<space>start<null>
mov si,offset forstr1 ; build composite command string
mov di,offset rdbuf+2 ; starting at rdbuf+2
call strcpy ; 'forinc '
mov si,offset decbuf ; 'variable'
call strcat
mov si,offset space ; space null
call strcat
mov si,forstepptr ; 'step'
call strcat
mov si,offset forstr2 ; cr,'if not > '
call strcat
cmp byte ptr temp,'-' ; negative step?
jne for4a ; ne = no
mov dx,offset rdbuf+2
call strlen
add dx,cx ; points at trailing null
mov si,dx
mov byte ptr [si-2],'<' ; reverse sense of test for neg step
for4a: mov si,offset decbuf ; 'variable'
call strcat
mov si,offset space ; space null
call strcat
mov si,forendptr ; 'end'
call strcat
mov si,offset space ; space null
call strcat
mov si,forcmdsptr ; 'commands'
call strcat
mov dx,offset rdbuf+2 ; string is built at rdbuf+2
call strlen
mov ax,cx ;
add ax,2+1 ; bytes needed plus ending CR
call malloc
mov es,ax ; seg
mov di,2 ; start two bytes in
mov si,offset rdbuf+2
push cx
cld
rep movsb ; copy from rdbuf+2 to malloc'd area
pop cx
mov al,CR
stosb
inc cx ; count CR in macro
call takopen_macro ; open a macro
mov bx,takadr ; point to current macro structure
mov ax,es ; segment of definition
mov [bx].takbuf,ax ; segment of definition string struc
mov [bx].takcnt,cx ; number of chars in definition
mov es:[0],cx ; buffer usage, for rewinding
mov [bx].takargc,0 ; our argument count
mov [bx].takptr,2 ; offset to read next command char
or [bx].takattr,take_malloc ; free buffer when done
or [bx].takattr,take_while
clc
ret
FORCMD endp
; Perform "inc variable step" from first two command line words
_forinc proc near
mov ah,cmword ; read variable name
mov comand.cmper,1 ; don't expand variable names here
mov bx,offset rdbuf+2 ; buffer
xor dx,dx ; no help
call comnd
jc forincx ; c = failure
mov word ptr rdbuf,ax ; save length of macro name
mov si,offset mcctab ; table of macro names
cld
lodsb
xor ch,ch
mov cl,al ; number of macro entries
or al,al
jnz forinc4 ; nz = have some
forincx:mov ah,cmeol ; kill rest of line
mov comand.cmcnvkind,cmcnv_crprot ; allow CR within {..}
call comnd
stc
ret
; find variable
forinc4:push cx ; save loop counter
lodsw ; length of macro name to ax
mov cx,word ptr rdbuf ; length of user's string
cmp ax,cx ; variable name same as user spec?
jne forinc6 ; ne = no, no match
push ax
push si ; save these around match test
mov di,offset rdbuf+2 ; user's string
forinc5:mov ah,[di]
inc di
lodsb ; al = mac name char, ah = user char
and ax,not 2020h ; clear bits (uppercase chars)
cmp ah,al ; same?
loope forinc5 ; while equal, do more
pop si ; restore regs
pop ax
jne forinc6 ; ne = no match
pop cx ; remove loop counter
jmp short forinc7 ; e = match
forinc6:add si,ax ; point to next name, add name length
add si,2 ; and string pointer
pop cx ; recover loop counter
loop forinc4 ; one less macro to examine
jmp forincx ; failed to locate
forinc7:mov ax,[si-2] ; get length of variable string
add si,ax ; point to segment of definition
mov si,[si] ; seg of definition
push es
mov es,si
mov cx,es:[0] ; length of definition
mov di,offset rdbuf+2 ; variable name from user
add di,[di-2] ; plus length of variable name
mov byte ptr [di],' ' ; <count><varname><space>
inc di
mov si,2 ; skip over definition count word
forinc9:mov al,es:[si] ; copy string to regular data segment
mov [di],al
inc si
inc di
loop forinc9
pop es
mov byte ptr [di],'+'
inc di
push di ; save place after '+'
mov bx,di ; optional step goes here
mov ah,cmword ; get step size, if any
xor dx,dx ; no help at this level
call comnd
pop di
jc forincx ; c = fail
; now convert step size, if any
or ax,ax ; is length zero?
jnz forinc15 ; nz = no, convert number to binary
mov word ptr [di],'1' ; put '1' where optional is missing
forinc15:
mov di,offset rdbuf+2 ; user's variable name
add di,[di-2] ; its length
inc di ; skip space separator
push di ; save for place to write result
mov dx,di
call strlen ; get string length
mov domath_cnt,cx
mov domath_ptr,dx
call domath ; convert to number in dx:ax
cmp domath_cnt,0 ; converted whole word?
pop di ; clean stack
jne forincx ; ne = no, fail
; step size is in ax
or dx,dx ; is result negative?
jns forinc16 ; ns = no, positive or zero
neg dx ; flip sign
neg ax
sbb dx,0
mov byte ptr [di],'-' ; show minus sign
inc di
forinc16:call lnout ; binary to ascii decimal in ds:di
mov dx,offset rdbuf+2 ; place of <var><space><value>
call strlen ; length to cx for dodecom
call dodecom ; re-define variable
clc ; return to let rest of cmd execute
ret ; as an IF statement
_forinc endp
; Convert numeric expression to string of digits as a replacement, asciiz.
; Enter with BX=start of expression, AX= length of expression.
; Returns BX=null at end of number and carry clear if success,
; or carry set and no change if failure
todigits proc near
mov domath_ptr,bx ; source text
mov domath_cnt,ax ; length
call domath
jnc todigits1 ; nc = converted value
ret ; fail
todigits1:
push di
mov di,bx ; where to write
or dx,dx ; is result negative?
jns todigits2 ; ns = no, positive or zero
neg dx ; flip sign
neg ax
sbb dx,0
mov byte ptr [di],'-' ; show minus sign
inc di
todigits2:
call lnout ; convert DX:AX to ASCIIZ in DS:DI
mov bx,di ; point to trailing null
pop di
clc ; success
ret
todigits endp
; Initialize macro IBM at Kermit startup time
initibm proc near
mov si,offset ibmmac ; text of IBM macro
mov di,offset rdbuf+2 ; where command lines go
call strcpy ; copy it there
mov dx,di ; get length of command line
call strlen ; set cx to length, for dodecom
call dodecom ; now define the macro
mov rdbuf+2,0
mov si,offset dialmac
mov di,offset rdbuf+2
call strcpy
mov dx,di
call strlen
inc cx
jmp dodecom ; now define the macro
initibm endp
; Open an text subsititution macro. No buffer is allocated.
takopen_sub proc far
cmp taklev,maxtak ; room in take level?
jb takosub1 ; b = yes
mov dx,offset ermes4 ; say too many Take files
mov ah,prstr ; display error message
int dos
stc ; set carry for failure
ret
takosub1:push ax
push bx
mov bx,takadr ; previous take structure
push [bx].takargc ; stash argument count
push [bx].takctr ; stash COUNT
add takadr,size takinfo ; pointer to new Take structure
inc taklev
mov bx,takadr ; pointer to new Take structure
pop [bx].takctr ; copy in old count
pop [bx].takargc ; copy in old argc
xor ax,ax
mov [bx].takbuf,ax ; seg of memory block
mov [bx].takptr,2 ; where to read first
mov [bx].takcnt,ax ; unread bytes in buffer
mov [bx].takper,al ; expand macros
mov [bx].takattr,al ; attribute, none
mov [bx].taktyp,take_sub ; kind is text substitution
mov [bx].takinvoke,0
pop bx
pop ax
clc
ret
takopen_sub endp
; Open take structure for file input. Buffer of tbufsiz is preallocated
; and pointed to by takbuf:takptr.
takopen_file proc far
call takopen_sub ; do substitution macro busy work
jnc takofil1 ; nc = success so far
ret ; fail
takofil1:push bx
mov bx,takadr
mov ax,tbufsiz ; size of buffer
call malloc
jnc takofil2 ; nc = success
pop bx
ret ; fail
takofil2:mov [bx].takbuf,ax ; seg of allocated buffer
mov [bx].takattr,take_malloc ; remember so takclos will free it
mov [bx].taktyp,take_file ; disk file kind
mov [bx].takhnd,0 ; file handle
mov word ptr [bx].takseek,0
mov word ptr [bx].takseek+2,0 ; seek distance, bytes
or [bx].takattr,take_autocr ; need auto CR at EOF
mov [bx].takinvoke,0
pop bx
clc
ret
takopen_file endp
; Open an internal (macro) structure. No buffer is allocated.
; Return carry clear for success, carry set for failure.
takopen_macro proc far
push ax
push bx
push cx
push dx
cmp taklev,maxtak ; room in take level?
jb takoma1 ; b = yes
mov dx,offset ermes4 ; say too many Take files
mov ah,prstr ; display error message
int dos
stc ; set carry for failure
jmp takoma2
takoma1:xor ax,ax
xor cx,cx
cmp taklev,0 ; at top level now?
je takoma3 ; e = yes
mov bx,takadr
mov ax,[bx].takargc ; get argument count
mov cx,[bx].takctr ; get COUNT
takoma3:add takadr,size takinfo ; pointer to new Take structure
inc taklev
mov bx,takadr ; pointer to new Take structure
mov [bx].takargc,ax ; copy in old argc
mov [bx].takctr,cx ; copy in old count
xor ax,ax
mov [bx].takbuf,ax ; no segment of Take buffer
mov [bx].takcnt,ax ; number of unread bytes
mov [bx].takptr,2 ; init pointer to definition itself
mov [bx].takper,al ; expand macros
mov [bx].takattr,take_autocr ; need auto CR at EOF
mov [bx].taktyp,take_macro ; macro
mov [bx].takinvoke,0
clc ; carry clear for success
takoma2:pop dx
pop cx
pop bx
pop ax
ret
takopen_macro endp
; Close Take file. Enter at Take level to be closed.
; Closes disk file, pops Take level.
TAKCLOS PROC FAR
cmp taklev,0 ; anything to close?
jg takclo1 ; g = yes
ret
takclo1:push ax
push bx
push cx
mov bx,takadr
test [bx].takattr,take_malloc ; new malloc'd buffer in takbuf?
jz takclo2 ; z = no
mov ax,[bx].takbuf
push es
mov es,ax ; seg of separately malloc'd buffer
mov ah,freemem ; free it
int dos
pop es
and [bx].takattr,not take_malloc ; no extra buffer to free
takclo2:mov al,[bx].taktyp
cmp al,take_macro ; macro?
je takclo3 ; e = yes
cmp al,take_file ; disk file?
jne takclo6 ; ne = no, leaves sub and comand kinds
mov word ptr [bx].takseek,0 ; disk file
mov word ptr [bx].takseek+2,0 ; seek distance, bytes
mov bx,[bx].takhnd ; get file handle
mov ah,close2 ; close file
int dos
jmp short takclo6
; macros, remove argument array
takclo3:cmp [bx].takargc,0 ; any arguments to macro?
je takclo5 ; e = no
mov word ptr settemp,3 ; remove \%0..9 macros. length word
mov word ptr settemp+2,'%\' ; "\%digit"
mov settemp+4,'0'
takclo4:mov di,offset settemp ; buffer remtab reads
call remtab ; remove macro
inc settemp+4 ; next digit
cmp settemp+4,'9' ; done last?
jbe takclo4 ; be = no
takclo5:call unhidemac ; rename previous hidden macros
takclo6:mov bx,takadr ; all kinds of Take
xor al,al ; get a null
mov [bx].taktyp,al ; clear to avoid confusion
mov [bx].takper,al ; macro expansion flag
mov [bx].takattr,al ; attributes
dec taklev ; pop macro Take level
sub takadr,size takinfo ; get previous Take's address
pop cx
pop bx
pop ax
ret
TAKCLOS ENDP
; POP/END command. Defend against command parser closing the Take/Macro at
; the end of file. Return optional trailing number in ERRORLEVEL (errlev).
POPCMD proc near
mov oldifelse,0 ; don't permit ELSE after failed IF
mov ifelse,0
mov ah,cmword ; get optional error value and msg
mov bx,offset rdbuf
mov dx,offset pophlp ; help on numerical argument
mov comand.cmcr,1 ; bare c/r's allowed
call comnd
mov comand.cmcr,0 ; restore normal state
jc popcmdx ; c = failure
mov ah,cmline ; get optional error value and msg
mov bx,offset rdbuf+100
mov dx,offset pophlp ; help on numerical argument
mov comand.cmcr,1 ; bare c/r's allowed
mov comand.cmdonum,1 ; \number conversion allowed
call comnd
mov comand.cmcr,0 ; restore normal state
jc popcmdx ; c = failure
mov domath_ptr,offset rdbuf
mov domath_cnt,ax
call domath ; convert to number in ax
jc popcmd2 ; c = not a number
mov errlev,al ; return value in ERRORLEVEL
mov kstatus,ax ; and in STATUS
mov si,offset rdbuf+100
popcmd1:lodsb ; read a msg char
or al,al ; null terminator?
jz popcmd2 ; z = empty string
cmp al,' ' ; leading white space?
je popcmd1 ; be = leading white space
dec si ; backup to non-white char
mov dx,offset crlf
mov ah,prstr
int dos
mov dx,si ; message
call prtasz
popcmd2:call poplevel ; do the pop
popcmdx:ret
POPCMD endp
; Common Get keyword + Get Confirm sequence. Call with dx = keyword table,
; bx = help message offset. Returns result in BX. Modifies AX, BX.
; Returns carry clear if sucessful else carry set. Used in many places below.
keyend proc near
mov ah,cmkey
call comnd
jnc keyend1 ; nc = success
ret ; failure
keyend1:push bx ; save returned results around call
mov ah,cmeol ; get c/r confirmation
call comnd
pop bx ; recover keyword 16 bit value
ret ; return with carry from comnd
keyend endp
srvdsa proc near ; DISABLE Server commands
mov dx,offset srvdetab
mov bx,offset sdshlp
call keyend
jc srvdsa1 ; c = failure
cmp apctrap,0 ; disable from APC
jne srvdsa1 ; ne = yes
or denyflg,bx ; turn on bit (deny) for that item
srvdsa1:ret
srvdsa endp
srvena proc near ; ENABLE Server commands
mov dx,offset srvdetab ; keyword table
mov bx,offset sdshlp ; help on keywords
call keyend
jc srvena1 ; c = failure
cmp apctrap,0 ; disable from APC
jne srvena1 ; ne = yes
not bx ; invert bits
and denyflg,bx ; turn off (enable) selected item
srvena1:ret
srvena endp
; DIAL arg list
; Invokes macro DIAL with args or, if not present, then macro "\0IAL"
; defined above, with args.
dial proc near
mov kstatus,kssuc ; assume success
mov word ptr decbuf,4 ; length of our name
mov word ptr decbuf+2,'ID' ; prefix with "DIAL "
mov word ptr decbuf+4,'LA'
call dialcom ; look for macro "DIAL"
jnc dial1 ; nc = found "DIAL"
mov si,offset dialmac ; default string "__DIAL"
mov di,offset decbuf+2 ; destination
push es
mov ax,seg decbuf
mov es,ax
mov cx,6 ; string length
cld
rep movsb ; copy string
pop es
mov word ptr decbuf,6 ; string length
call dialcom ; look for it
jc dialx ; c = failed, quit
dial1: jmp docom1 ; DO macro with bx set for domacptr
dialx: mov kstatus,kstake ; Take file command failure
stc ; fail
ret
dial endp
; Worker for DIAL command. Find macro whose name is in offset decbuf+2
; and whose length is in word ptr decbuf.
; Return carry clear and macro seg in BX if success, else carry set.
dialcom proc near
push si
push di
push es
mov ax,ds
mov es,ax ; check for existence of macro
mov bx,offset mcctab ; table of macro names
mov cl,[bx] ; number of names in table
xor ch,ch
jcxz dialcx ; z = empty table, do nothing
inc bx ; point to length of first name
dialc2: mov ax,[bx] ; length of this name
cmp ax,word ptr decbuf ; length same as desired keyword?
jne dialc3 ; ne = no, search again
mov si,bx
add si,2 ; point at first char of macro name
push cx ; save name counter
push di ; save reg
mov cx,word ptr decbuf ; length of name
mov di,offset decbuf+2 ; point at desired macro name
push es ; save reg
push ds
pop es ; make es use data segment
cld
repe cmpsb ; match strings
pop es ; need current si below
pop di ; recover saved regs
pop cx
jne dialc3 ; ne = not matched
add bx,ax ; length of name
add bx,2 ; count + name, points at word ptr
mov bx,[bx] ; return word ptr in BX
clc ; say success
jmp short dialcx ; and return
dialc3: add bx,ax ; step to next name, add name length
add bx,4 ; + count and def word ptr
loop dialc2 ; try next name
stc ; say failure
dialcx: pop es
pop di
pop si ; no macro
ret
dialcom endp
; This is the SET command
; Called analyzers return carry clear for success, else carry set.
SETCOM PROC NEAR ; Dispatch all SET commands from here
mov kstatus,kssuc ; global status, success
mov dx,offset settab ; Parse a keyword from the set table
mov bx,offset sethlp
mov ah,cmkey
call comnd
jc setcom1 ; c = failure
jmp bx ; execute analyzer routine
setcom1:ret
SETCOM endp
SETATT PROC NEAR ; Set attributes on | off
mov dx,offset atttab
xor bx,bx
mov ah,cmkey
call comnd
jc setatt3 ; c = failure
mov dx,bx ; hold results in dx
cmp dl,0ffh ; ON/OFF (all of them)?
je setatt1 ; e = yes
push dx
mov dx,offset ontab ; get on/off state
xor bx,bx
mov ah,cmkey
call comnd
pop dx
jc setatt3 ; c = failure
mov dh,bl ; store on/off state in dh
setatt1:push dx
mov ah,cmeol
call comnd
pop dx
jc setatt3
mov al,flags.attflg ; current flags
not dl ; all but those affected
and al,dl ; turn off affected flags
or dh,dh ; off (dh = 0)?
jz setatt2 ; z = yes
not dl ; affected flags back again as ones
or al,dl ; turn on affected flags
setatt2:mov flags.attflg,al
setatt3:ret
SETATT ENDP
; SET BAUD or SET SPEED
; See system dependent routine BAUDST in file MSXxxx.ASM
; SET BELL on or off
BELLST PROC NEAR
mov dx,offset ontab ; on/off table
xor bx,bx ; help
call keyend
jc bellst1 ; c = failure
mov flags.belflg,bl
bellst1:ret
BELLST ENDP
; SET BLOCK-CHECK
BLKSET PROC NEAR
mov dx,offset blktab ; table
xor bx,bx ; help, use table
call keyend
jc blkset1 ; c = failure
mov dtrans.chklen,bl ; use this char as initial checksum
blkset1:ret
BLKSET ENDP
; SET CARRIER {ON, OFF}
setcar proc near
mov dx,offset ontab ; table
mov bx,offset carhlp ; help, use table
call keyend
jc setcar1 ; c = failure
mov flags.carrier,bl ; value
mov cardet,0 ; clear carrier detect variable
clc
setcar1:ret
setcar endp
; Set port addresses for COM1 .. COM4 at Kermit initialization time via
; Environment. Called by command parser while doing Environment reading in
; mssker.asm and via SET COM1 .. SET COM4.
COM1PORT proc near
mov bx,0 ; offset of com1 port address
jmp short comport
COM1PORT endp
COM2PORT proc near
mov bx,2 ; offset of com2 port address
jmp short comport
COM2PORT endp
COM3PORT proc near
mov bx,4 ; offset of com3 port address
jmp short comport
COM3PORT endp
COM4PORT proc near
mov bx,6 ; offset of com4 port address
;; jmp comport
COM4PORT endp
COMPORT proc near ; worker for above
push bx ; save offset
shr bx,1 ; address bytes 0..3
mov ah,portfifo[bx] ; save existing port values
mov al,portirq[bx]
mov temp2,ax ; worker word
mov bx,offset rdbuf
mov dx,offset comhlp
mov ah,cmword ; get port address number
call comnd
jnc compor3
pop bx ; fail
ret
compor3:mov numerr,0 ; no error message
mov min,100h ; smallest number
mov max,0fff0h ; largest magnitude
mov numhlp,0 ; help
call numwd ; parse this word
jnc compor4 ; nc = success, value in ax
pop bx
ret
compor4:mov temp1,ax ; save port address
mov bx,offset rdbuf
mov dx,offset irqhlp
mov ah,cmword ; read IRQ
call comnd
jnc compor5
pop bx
ret
compor5:
push ax
push bx
mov ah,cmkey
mov bx,offset fifohlp ; help
mov dx,offset FIFOtab ; action table
mov comand.cmcr,1 ; null response permitted
call comnd
jc compor8 ; c = nothing present
mov byte ptr temp2+1,bl ; save FIFO setting
compor8:pop bx
pop ax
push ax
mov ah,cmeol ; get command confirmation
call comnd
pop ax
jnc compor5a ; nc = success
ret
compor5a:or ax,ax ; anything given?
jz compor7 ; z = no
mov numhlp,0 ; help
mov numerr,0 ; no error message
mov min,2 ; smallest number
mov max,15 ; largest magnitude
call numwd ; parse this word
jnc compor6 ; nc = success
pop bx
ret
compor6:mov byte ptr temp2,al ; save IRQ
compor7:pop bx ; recover offset
cmp word ptr machnam,'BI' ; check for "IBM-PC"
jne compor1 ; ne = not this name, fail
cmp word ptr machnam+2,'-M'
jne compor1
cmp word ptr machnam+4,'CP'
jne compor1
push es
mov al,flags.comflg ; current comms port
dec al ; count from 0, as per Bios
shl al,1 ; double to use word index of Bios
cmp al,bl ; using this port now?
jne compor2 ; ne = no
call serrst ; reset the port
compor2:mov cx,40h ; segment 40h
mov es,cx
mov ax,temp1 ; port address
mov es:[bx],ax ; set port address
pop es
shr bl,1 ; coms port offset 0,2,4,6 to 0,1,2,3
mov ax,temp2 ; FIFO and IRQ
mov portirq[bx],al ; IRQ
mov portfifo[bx],ah ; FIFO
clc
compor1:ret
COMPORT endp
; Set CONTROL PREFIXED <code>, CONTROL UNPREFIXED <code>, code can be ALL
cntlset proc near
push es
mov di,seg decbuf ; copy protlist to work buffer decbuf
mov es,di
mov si,offset protlist
mov di,offset decbuf
mov cx,32
cld
rep movsb
pop es
mov dx,offset cntltab ; table
mov bx,offset cntlhlp ; help
mov ah,cmkey
call comnd
jc cntlsetx ; c = failure
mov rdbuf,bl ; save operation value
cntlse1:mov ah,cmword ; get optional error value and msg
mov bx,offset rdbuf+1
mov dx,offset ctlhlp ; help on numerical argument
call comnd
jc cntlsetx ; c = failure
mov si,offset rdbuf+1 ; skip operational value in rdbuf
or ax,ax ; anything given?
jnz cntlse2 ; nz = yes
mov ah,cmeol ; confirm
call comnd
jc cntlsetx ; c = failure
push es ; copy work buffer decbuf to protlist
mov di,seg protlist
mov es,di
mov di,offset protlist
mov si,offset decbuf
mov cx,32
cld
rep movsb
pop es
clc
ret
cntlse2:mov al,[si] ; look for ALL
or al,al ; end of string?
jz cntlse1 ; z = yes, get more user input
cmp al,',' ; comma separator?
jne cntlse2a ; ne = no
inc si ; skip it
jmp short cntlse2
cntlse2a:or al,20h ; to lower
cmp al,'a' ; a in ALL?
je cntlse8 ; e = got ALL
cntlse3:mov domath_ptr,si
mov domath_cnt,16
call domath ; convert to number in ax
jc cntlsety ; c = failure
mov si,domath_ptr ; next byte
cmp al,159 ; out of range?
ja cntlsety ; a = yes
cmp al,128 ; in 8-bit range?
jae cntlse4 ; ae = yes
cmp al,31 ; out of range?
ja cntlsety ; a = yes
cntlse4:mov ah,rdbuf ; protected/unprotected pointer 0/1
mov bl,al ; char
and bl,not 80h ; strip high bit from index
xor bh,bh
or ah,ah ; protecting?
jz cntlse6 ; z = yes
mov ah,1 ; assume unprotecting 7-bit char
and al,80h ; get high bit
jz cntlse5 ; z = no high bit
mov ah,80h ; set high bit flag
cntlse5:or decbuf[bx],ah ; set unprotection bit
jmp cntlse2 ; get more input
cntlse6:mov ah,1 ; assume protecting 7-bit char
and al,80h ; get high bit
jz cntlse7 ; z = no high bit
mov ah,80h ; set high bit flag
cntlse7:not ah ; invert bits
and decbuf[bx],ah ; clear the unprotection bit
jmp cntlse2 ; get more input
cntlsetx:ret ; success or failure
; process ALL
cntlse8:mov cx,32
xor bx,bx
mov al,rdbuf ; get kind of operation
or al,al ; prefix (0)?
je cntlse9 ; e = yes
mov al,81h ; unprefix all (7 and 8 bit)
cntlse9:mov decbuf[bx],al ; set the state
inc bx
loop cntlse9 ; do all
jmp cntlse1 ; get more user input
cntlsety:mov ah,cmeol ; confirm
call comnd
mov ah,prstr
mov dx,offset badcntlmsg ; say out of range
int dos
stc
ret
cntlset endp
; SET COUNTER number for script IF COUNTER number <command>
TAKECTR PROC NEAR
mov min,0 ; get decimal char code
mov max,65535 ; range is 0 to 65535 decimal
mov numhlp,offset takchlp ; help message
mov numerr,0 ; error message
call num0 ; convert number, return it in ax
jc takect2 ; c = error
push ax ; save numerical code
mov ah,cmeol
call comnd ; get a confirm
pop ax ; recover ax
jc takect2 ; c = failure
cmp taklev,0 ; in a Take file?
je takect4 ; e = no
push bx
mov bx,takadr
mov [bx].takctr,ax ; set COUNT value
pop bx
clc ; success
takect2:ret
takect4:mov dx,offset takcerr ; say must be in Take file
jmp reterr ; display msg and return carry clear
TAKECTR ENDP
; RESET
reset proc near
mov dx,offset resettab
xor bx,bx
call keyend
jnc reset1 ; nc = success
ret ; failure
reset1: mov al,bl ; reset clock
mov bx,portval
mov starttime[bx+3],bl ; remember in high byte
ret
reset endp
; SET DEBUG {OFF | ON | SESSSION | PACKETS}
DEBST PROC NEAR
mov dx,offset debtab
mov bx,offset debhlp
call keyend
jnc debst1 ; nc = success
ret ; failure
debst1: or flags.debug,bl ; set the mode, except for Off
or bx,bx ; OFF?
jnz debst2 ; nz = no
mov flags.debug,bl ; set the DEBUG flags off
debst2: clc ; success
ret
DEBST ENDP
; SET DESTINATION of incoming files
DESSET PROC NEAR
mov dx,offset destab
xor bx,bx
call keyend
jc desset1 ; c = failure
mov flags.destflg,bl ; set the destination flag
desset1:ret
DESSET ENDP
; SET DEFAULT-DISK for sending/receiving, etc
; See cwdir in file mssker
; SET DELAY seconds Used only for SEND command in local mode
SETDELY PROC NEAR
mov min,0 ; smallest acceptable value
mov max,63 ; largest acceptable value
mov numhlp,offset delyhlp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc setdly1 ; c = error
mov trans.sdelay,al
setdly1:ret ; success or failure
SETDELY ENDP
; SET DISPLAY Quiet/Regular/Serial/7-Bit/8-Bit (inverse of Set Remote on/off)
; Accepts two keywords in one command
disply proc near
mov ah,cmkey
mov dx,offset distab
mov bx,offset dishlp
call comnd
jnc displ0 ; nc = success
ret ; return failure
displ0: mov temp1,bx ; save parsed value
mov temp2,0ffffh ; assume no second keyword
mov comand.cmcr,1 ; bare CR's are allowed
mov ah,cmkey ; parse for second keyword
mov dx,offset distab
mov bx,offset dishlp
call comnd
jc displ1 ; no keyword
mov temp2,bx ; get key value
displ1: mov comand.cmcr,0 ; bare CR's are not allowed
mov ah,cmeol
call comnd ; confirm
jnc displ2 ; nc = success
ret ; failure
displ2: mov ax,temp1 ; examine first key value
call dispcom ; do common code
mov ax,temp2 ; examine second key value
dispcom:or ax,ax ; check range
jle dispc3 ; le = not legal, ignore
cmp al,7 ; 7-8 bit value?
jge dispc2 ; ge = yes
and flags.remflg,not(dquiet+dregular+dserial)
or flags.remflg,al ; set display mode
clc ; success
ret ; check next key value
dispc2: cmp al,8 ; set 8-bit wide display?
ja dispc3 ; a = bad value
and flags.remflg,not d8bit ; assume want 7 bit mode
cmp al,7 ; really want 7 bit mode?
je dispc3 ; e = yes
or flags.remflg,d8bit ; set 8 bit flag
dispc3: clc ; success
ret ; end of display common code
disply endp
; Set Dump filename for saving screen images on disk.
; Puts filename in global string dmpname
setdmp proc near
mov bx,offset rdbuf ; work area
mov dx,offset dmphlp ; help message
mov ah,cmword ; allow paths
call comnd
jc setdmp2 ; c = failure
mov ah,cmeol
call comnd
jc setdmp2 ; c = failure
mov dx,offset rdbuf ; assume we will use this text
call strlen ; filename given?
mov si,dx ; for strcpy
or cx,cx ; length of user's filename
jg setdmp1 ; g = filename is given
mov si,offset dmpdefnam ; no name, use default instead
setdmp1:mov di,offset dmpname ; copy to globally available loc
call strcpy
clc
setdmp2:ret
setdmp endp
; Set DUPLEX {FULL, HALF}
setdup proc near
xor bx,bx
mov dx,offset duptab
call keyend
jc setdup1 ; c = failure
mov si,portval
mov [si].duplex,bl ; set value
mov [si].ecoflg,0 ; turn off local echoing
or bl,bl ; full duplex?
jz setdup1 ; z = yes
mov [si].floflg,0 ; no flow control for half duplex
mov [si].ecoflg,1 ; turn on local echoing
call serrst ; reset port so opening uses above
setdup1:ret
setdup endp
; SET EOF
SETEOF PROC NEAR
xor bx,bx
mov dx,offset seoftab
call keyend
jc seteof1 ; c = failure
mov flags.eofcz,bl ; set value
seteof1:ret
SETEOF ENDP
; SET End-of-Packet char (for Sent packets)
; Archic, here for downward compatibility
EOLSET PROC NEAR
mov stflg,'S' ; set send/receive flag to Send
jmp sreol ; use Set Send/Rec routine do the work
EOLSET ENDP
; SET ERRORLEVEL number
SETERL PROC NEAR
mov numhlp,offset erlhlp ; help
mov numerr,0 ; error message
mov min,0 ; smallest number
mov max,255 ; largest magnitude
call num0 ; parse numerical input
jc seterl1 ; c = error
mov errlev,al ; store result
clc
seterl1:ret
SETERL ENDP
; SET ESCAPE character.
; Accept literal control codes and \### numbers. [jrd] 18 Oct 1987
ESCSET PROC NEAR
mov ah,cmword
mov bx,offset rdbuf ; work space
mov dx,offset eschlp ; help
call comnd
jc escse2 ; c = failure
or ax,ax ; anything given?
jnz escse1 ; nz = yes
mov dx,offset ermes6 ; more parameters needed
jmp reterr
escse1: push ax ; save string length
mov ah,cmeol ; get a confirm
call comnd
pop ax
jc escse2 ; c = failure
mov domath_ptr,offset rdbuf
mov domath_cnt,ax
call domath ; convert to number in ax
cmp ax,spc ; is it a control code?
jae escse3 ; ae = no, complain
or ax,ax ; non-zero too?
jz escse3 ; z = zero
mov trans.escchr,al ; save new escape char code
clc
escse2: ret
escse3: mov dx,offset escerr
jmp reterr
ESCSET ENDP
; Set EXIT
; SET WARNING {ON, OFF}
setexitwarn proc near
mov dx,offset exittab ; exit table
xor bx,bx
mov ah,cmkey
call comnd
jc setexit1
or bl,bl ; warning?
jnz setexit1 ; nz = no
mov bx,offset exitwhlp ; warning help
mov dx,offset ontab
call keyend
jc setexit1 ; c = failure
mov flags.exitwarn,bl ; set value
setexit1:ret
setexitwarn endp
; SET FILE {DISPLAY, WARNING, TYPE, CHARACTER-SET}
SETFILE proc near
mov dx,offset setfitab ; SET FILE table
xor bx,bx
mov ah,cmkey
call comnd
jc setfiy ; c = failure
or bl,bl ; Warning?
jnz setfi1 ; nz = no
; entry point for old SET WARNING
FILWAR: mov dx,offset warntab ; warning table, on, off, no-super
xor bx,bx
call keyend
jc setfiy ; c = failure
mov flags.flwflg,bl ; set the filewarning flag
setfiy: ret
setfi1: cmp bl,1 ; SET FILE CHARACTER-SET?
jne setfi2 ; ne = no
mov dx,offset setchtab ; table of char sets
xor bx,bx
call keyend ; get the set id
jc setfiy ; c = error
mov flags.chrset,bx ; save the id
cmp bx,866 ; setting CP866?
jne setfi1a ; ne = no
cmp dtrans.xchset,xfr_cyrillic ; using TRANSFER of Cryillic?
je setfi1a ; e = yes
mov dtrans.xchset,xfr_cyrillic ; force TRANSFER of Cyrillic
mov trans.xchset,xfr_cyrillic
mov ah,prstr
mov dx,offset setchmsg ; show warning
int dos
clc
ret
setfi1a:cmp bx,932 ; setting Shift-JIS?
jne setfi1b ; ne = no
mov dtrans.xchset,xfr_japanese ; force TRANSFER of Japanese-EUC
mov trans.xchset,xfr_japanese
mov ah,prstr
mov dx,offset setchmsg2 ; show warning
int dos
clc
ret
setfi1b:cmp bx,862 ; setting CP862?
jne setfi1c ; ne = no
mov dtrans.xchset,xfr_hebiso ; force TRANSFER of Latin-Hebrew
mov trans.xchset,xfr_hebiso
mov ah,prstr
mov dx,offset setchmsg3 ; show warning
int dos
setfi1c:clc
ret
setfi2: cmp bl,2 ; SET FILE TYPE?
jne setfi3 ; ne = 3
mov dx,offset xftyptab ; table of types
xor bx,bx
call keyend
jc setfix ; c = error
mov dtrans.xtype,bl ; store transfer type
mov trans.xtype,bl ; store transfer type
ret
setfi3: cmp bl,3 ; SET FILE DISPLAY?
jne setfi4 ; ne = no
mov dx,offset distab2 ; table
xor bx,bx
call keyend
jc setfix ; c = failure
and flags.remflg,not(dquiet+dregular+dserial)
or flags.remflg,bl ; set display mode
clc
setfix: ret
setfi4: cmp bl,4 ; SET FILE INCOMPLETE?
jne setfix ; ne = no
; SET INCOMPLETE file disposition
ABFSET: mov dx,offset abftab
xor bx,bx
call keyend
jc abfset1 ; c = failure
mov flags.abfflg,bl ; Set the aborted file flag
abfset1:ret
SETFILE endp
; SET FLOW-CONTROL {NONE, XONXOFF, RTS/CTS}
FLOSET PROC NEAR
mov dx,offset flotab
xor bx,bx
call keyend
jc floset3 ; c = failure
mov si,portval
mov ax,floxon ; xon/xoff pair
or bx,bx ; any flow control?
jz floset1 ; z = none
test bx,1+2 ; using xon/xoff?
jnz floset2 ; nz = xon/xoff
cmp flags.comflg,'F'
je floset1
cmp flags.comflg,4 ; UART? (RTS/CTS case)
ja floset4 ; a = no, error
floset1:xor ax,ax ; clear chars for RTS/CTS and none
floset2:mov [si].flowc,ax ; flow control values
mov [si].floflg,bl ; flow control kind
clc
floset3:ret
floset4:mov dx,offset ermes7 ; error message
jmp reterr
FLOSET ENDP
; SET FOSSIL CLOSE-ON-DONE
FOSSET proc near
mov dx,offset fossiltab
xor bx,bx
mov ah,cmkey
call comnd
jc fossetx ; c = failure
mov dx,offset ontab ; get on/off state
mov bx,offset fossilhlp
mov ah,cmkey
call comnd
jnc fosset1
ret ; c = failure
fosset1:push bx
mov ah,cmeol
call comnd
pop bx
jc fossetx ; failure
mov fossilflag,bl ; set flag
clc
fossetx:ret
FOSSET endp
; SET HANDSHAKE
; Add ability to accept general decimal code.
HNDSET PROC NEAR
mov dx,offset hndtab ; table to scan
mov bx,offset hnd1hlp ; help message
mov ah,cmkey
call comnd
jc hnd2 ; c = failure
cmp bl,0ffh ; want a general char code?
jne hnd1 ; ne = no
mov min,0 ; get decimal char code
mov max,255 ; range is 0 to 255 decimal
mov numhlp,offset erlhlp ; help msg
mov numerr,0 ; error message
call num0 ; convert number, return it in ax
jc hnd2 ; c = error
mov bx,ax ; recover numerical code
hnd1: push bx ; handshake type
mov ah,cmeol
call comnd ; get a confirm
pop bx ; recover bx
jc hnd2 ; c = failure
mov si,portval
or bl,bl ; setting handshake off?
jz hnd0 ; z = yes
mov [si].hndflg,1 ; turn on handshaking
mov [si].hands,bl ; use this char as the handshake
clc ; success
ret
hnd0: mov [si].hndflg,bl ; no handshaking
clc ; success
hnd2: ret
HNDSET ENDP
;
; Set Input commands (default-timeout, timeout-action, case, echo)
; By Jim Strudevant [jrs]
INPSET PROC NEAR
mov ah,cmkey ; key word
mov dx,offset inptab ; from inputtable
xor bx,bx ; no hints
call comnd ; get the word
jc inpset1 ; c = failure
jmp bx ; do the sub command
inpset1:ret
;
; Set Input Default-timeout in seconds
;
inptmo: mov numhlp,offset intoms ; help
mov numerr,0 ; error message
mov min,0 ; smallest number
mov max,-1 ; largest magnitude
call num0 ; parse numerical input
jc inptmo1 ; c = error
mov script.indfto,ax ; store result
inptmo1:ret
;
; Set Input Timeout action (proceed or quit)
;
inpact: mov dx,offset inactb ; from this list
xor bx,bx ; no hints
call keyend ; get it
jc inpact1 ; c = failure
mov script.inactv,bl ; save the action
inpact1:ret
;
; Set Input Echo on or off
;
inpeco: mov dx,offset ontab ; from this list
xor bx,bx ; no hints
call keyend ; get it
jc inpeco1 ; c = failure
mov script.inecho,bl ; save the action
inpeco1:ret
;
; Set Input Case observe or ignore
;
inpcas: mov dx,offset incstb ; from this list
xor bx,bx ; no hints
call keyend ; get it
jc inpcas1 ; c = failure
mov script.incasv,bl ; save the action
inpcas1:ret
infilt: mov dx,offset ontab ; filter input, table
xor bx,bx
call keyend
jc infilt1
mov script.infilter,bl
infilt1:ret
INPSET ENDP
; Set length of script buffer for INPUT/REINPUT at Kermit initialization
; time via Environment. Called by command parser while doing Environment
; reading in mssker.asm. Do not call after Kermit has initialized.
SETINPBUF proc near
mov scpbuflen,128 ; store default buffer length
mov numhlp,0 ; no help
mov numerr,0 ; no error message
mov min,2 ; smallest number (must be non-zero)
mov max,65535 ; largest magnitude (16 bits worth)
call num0 ; parse numerical input
jc setinpbx ; c = error
mov scpbuflen,ax ; store result
clc
setinpbx:ret
SETINPBUF endp
; SET KEY
; Jumps to new Set Key routine
setkey proc near
cmp stkadr,0 ; keyboard translator present?
je setk4 ; e = no, use this routine
mov bx,stkadr ; yes, get offset of procedure
jmp bx ; jump to keyboard translator
setk4: mov dx,offset ermes5
jmp reterr ; else print error message
setkey endp
; SET LOCAL-ECHO {ON | OFF}
LCAL PROC NEAR
mov dx,offset ontab
xor bx,bx
call keyend
jc lcal1 ; c = failure
mov si,portval
mov [si].ecoflg,bl ; Set the local echo flag
lcal1: ret
LCAL ENDP
; LOG {PACKETS | SESSION | TRANSACTION} filename
setcpt proc near
mov dx,offset logtab ; kinds of logging
mov bx,offset loghlp ; help on kind of logging
mov ah,cmkey ; parse keyword
call comnd
jnc setcp20 ; nc = success
ret ; failure
setcp20:mov numhlp,bx ; save the parsed value
mov bx,offset rdbuf ; holds the complete filename
mov dx,offset filhlp ; ask for filename
mov ah,cmword ; allow paths
call comnd
jnc setcp21 ; nc = success
ret ; failure
setcp21:mov bx,offset rdbuf+100 ; optional APPEND or NEW keyword
mov dx,offset loghlp2 ; help with trailer keywords
mov ah,cmword ; allow paths
call comnd
jnc setcp21a ; nc = success
ret ; failure
setcp21a:mov ah,cmeol
call comnd ; get a confirm
jnc setcp22 ; nc = success
ret ; failure
setcp22:mov bx,numhlp ; recover kind of logging
mov dx,offset rdbuf ; length of filename to cx
call strlen ; length of given filename
test bl,logpkt ; packet logging?
jz setcp2 ; z = no, try others
mov dx,offset lpktnam ; filename
jcxz setcp1 ; z = no filename given
mov si,offset rdbuf ; get new name
mov di,dx ; destination
call strcpy ; replace old name
setcp1: cmp ploghnd,-1 ; packet log file already open?
je setcp6 ; e = no, open it
jmp setcp16 ; say file is open already
setcp2: test bl,logses ; session logging?
jz setcp4 ; z = no, try others
mov dx,offset lsesnam ; use default name
jcxz setcp3 ; z = no filename given
mov si,offset rdbuf ; get new name
mov di,dx ; destination
call strcpy ; replace old name
setcp3: cmp sloghnd,-1 ; transaction file already open?
je setcp6 ; e = no, open it
jmp setcp16 ; say file is open already
setcp4: test bl,logtrn ; transaction logging?
jz setcp14 ; z = no, error
mov dx,offset ltranam ; use default name
jcxz setcp5 ; z = no filename given
mov si,offset rdbuf ; get new name
mov di,dx ; destination
call strcpy ; replace old name
setcp5: cmp tloghnd,-1 ; transaction file already open?
je setcp6 ; e = no, open it
jmp setcp16 ; say file is open already
setcp6: mov ax,dx ; place for filename for isfile
call isfile ; does file exist already?
jc setcp7 ; c = does not exist so use create
test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
jnz setcp14 ; nz = no, use error exit
mov ah,open2 ; open existing file
mov al,1+1 ; for writing and reading
int dos
jc setcp14 ; if carry then error
mov bx,ax ; file handle for seeking
xor cx,cx ; high order displacement
xor dx,dx ; low order part of displacement
mov ah,lseek ; seek to EOF (to do appending)
mov al,2 ; says to EOF
int dos
mov di,word ptr rdbuf+100 ; trailing arg, get two letters
and di,not 2020h ; to upper case
cmp di,'EN' ; NEW?
jne setcp8 ; ne = no
mov dx,offset rdbuf ; filename
mov ah,del2 ; delete to create new file below
int dos
setcp7: test filtst.fstat,80h ; access problem?
jnz setcp14 ; nz = yes, stop here
mov ah,creat2 ; function is create
mov cx,20H ; turn on archive bit
int dos ; create the file, DOS 2.0
jc setcp14 ; if carry bit set then error
mov bx,ax ; file handle
setcp8: cmp numhlp,logpkt ; packet logging?
jne setcp9 ; ne = no
mov ploghnd,bx ; save transaction log handle here
jmp short setcp12
setcp9: cmp numhlp,logses ; session logging?
jne setcp10 ; ne = no
mov sloghnd,bx ; save session log handle here
jmp short setcp12
setcp10:mov tloghnd,bx ; save transaction log handle here
setcp12:mov ax,numhlp ; kind of Logging
or flags.capflg,al ; accumulate kinds of logging
clc ; success
ret
setcp14:mov dx,offset errcap ; give error message
jmp reterr ; and display it
setcp16:mov ah,prstr ; file already open
mov dx,offset erropn
int dos
clc ; return success
ret
setcpt endp
; SET MODE LINE
MODL PROC NEAR
mov dx,offset ontab ; parse an on or off
xor bx,bx ; no special help
call keyend
jc modl1 ; c = failure
mov flags.modflg,bl ; set flag appropriately
modl1: ret
MODL ENDP
; SET OUTPUT commands
setoutput proc near
mov dx,offset outputtab ; OUTPUT command table
xor bx,bx ; no special help
mov ah,cmkey
call comnd
jc setout1 ; c = failure
jmp short setopace
setout1:ret
setoutput endp
; Set OUTPUT Pacing <number millisec between chars>
setopace proc near
mov numhlp,offset opacehlp ; help
mov numerr,0 ; no error message
mov min,0 ; smallest number
mov max,65535 ; largest magnitude (16 bits worth)
call num0 ; parse numerical input
jc setopac1 ; c = error
mov outpace,ax ; store result
clc
setopac1:ret
setopace endp
; Set Macro Error
setmacerr proc near
mov dx,offset macrotab ; keyword
xor bx,bx
mov ah,cmkey
call comnd
jnc setmacer1
ret ; failure
setmacer1:
push bx ; save first keyword ident
mov dx,offset ontab ; on/off table
xor bx,bx
call keyend
pop ax ; first keyword ident
jnc setmacer2 ; nc = success
ret
setmacer2:or al,al ; "error" (0)?
jz setmacer3 ; z = yes
mov macroerror,bl ; set error action flag
setmacer3:clc
ret
setmacerr endp
; SET MODEM text creates macro named _MODEM
setmodem proc near
mov word ptr rdbuf+2,'m_' ; macro name "_modem"
mov word ptr rdbuf+4,'do'
mov word ptr rdbuf+6,'me'
mov rdbuf+8,' ' ; separator
mov bx,offset rdbuf+9
mov ax,length rdbuf-9 ; usable length of rdbuf
add ax,offset rdbuf ; ax = amount of buffer used
mov comand.cmblen,ax ; our new buffer length
mov comand.cmdonum,1 ; \number conversion allowed
mov ah,cmline ; get a line of text
mov dx,offset askhlp3 ; help, bx is buffer offset
push bx ; save starting offset
call comnd ; get macro definition text
pop bx
jnc setmod1 ; nc = success
ret ; failure
setmod1:mov cx,bx
sub cx,offset rdbuf+2 ; length of command line
jmp dodecom
setmodem endp
; SET PARITY
SETPAR PROC NEAR
mov dx,offset partab ; parity table
xor bx,bx
mov ah,cmkey
call comnd
jnc setp1 ; nc = success
ret
setp1: mov si,portval ; port structure
mov bh,[si].parflg ; current parity setting
or bh,bl ; merge hardware parity bits
mov byte ptr temp,bh ; save results around calls
test bl,PARHARDWARE ; using hardware parity?
jz setpt3 ; z = no
mov dx,offset parhwtab ; hardware parity table
xor bx,bx
mov ah,cmkey
call comnd
jnc setpt2
ret
setpt2: cmp flags.comflg,'4' ; physical serial port?
jbe setpt3 ; be = yes
mov dx,offset ermes8 ; say can't use Hardware on non-UART
jmp reterr
setpt3: mov ah,cmeol
push bx
call comnd
pop bx
jnc setpt4
ret
setpt4: mov si,portval ; port structure
mov [si].parflg,bl ; store the parity flag
test byte ptr temp,PARHARDWARE ; used hardware before or now?
jz setpt5 ; z = no
call serrst ; reset port for hardware reinit
setpt5: clc
ret
SETPAR ENDP
; Set Print filename for writing material to printers.
; Puts filename in global string prnname
setprn proc near
mov bx,offset rdbuf ; work area
mov dx,offset prnhlp ; help message
mov ah,cmword ; allow paths
call comnd
jc setprn3 ; c = failure
mov ah,cmeol
call comnd
jc setprn3 ; c = failure
mov dx,offset rdbuf ; assume we will use this text
call strlen ; filename given?
mov si,dx ; for strcpy
or cx,cx ; length of user's filename
jg setprn1 ; g = filename is given
mov si,offset prndefnam ; no name, use default instead
setprn1:mov di,offset prnname ; copy to globally available loc
call strcpy
cmp prnhand,0 ; handle already in use?
jle setprn2 ; le = no
call pntflsh ; flush current buffer
mov bx,prnhand ; close the file now
cmp bx,4 ; don't close DOS PRN
je setprn2 ; e = already available
mov ah,close2
int dos
setprn2:call prnopen ; open printer now, may set carry
jnc setprn3 ; nc = success
mov ah,prstr
push ds
mov dx,seg prnerr
mov ds,dx
mov dx,offset prnerr ; say can't open the file
int dos
pop ds
mov si,offset prndefnam ; use default name as fallback
mov di,offset prnname ; copy to globally available loc
call strcpy
mov prnhand,4 ; declare handle to be DOS PRN
setprn3:ret
setprn endp
; SET PROMPT Allow user to change the "Kermit-MS>" prompt
; {string} and \fchar(number) notation permitted to represent special chars.
; String will be made asciiz
PROMSET PROC NEAR
mov ah,cmline
mov bx,offset rdbuf ; read the prompt string
mov dx,offset prmmsg
mov comand.cmblen,length promptbuf -1 ; buffer length
mov comand.cmper,1 ; do not allow variable substitutions
call comnd
jc prom2 ; c = failure
or ax,ax ; prompt string?
jnz prom0 ; nz = yes
mov ax,offset kerm ; no, restore default prompt
jmp short prom1
prom0: mov si,offset rdbuf ; source = new prompt string
mov di,offset promptbuf ; destination
call strcpy ; copy string to final buffer
mov bx,ax ; get byte count
mov promptbuf[bx],0 ; insert null terminator
mov ax,offset promptbuf
prom1: mov prmptr,ax ; remember prompt buffer (old/new)
clc ; success
prom2: ret
PROMSET ENDP
; SET SERVER {LOGIN username password | TIMEOUT}
SETSRV PROC NEAR
mov dx,offset srvtab ; set server table
xor bx,bx ; use table for help
mov ah,cmkey ; get keyword
call comnd
jnc setsrv1 ; c = success
ret
setsrv1:cmp apctrap,0 ; disable from APC?
jne setsrvx ; ne = yes
cmp bl,1 ; Login?
jne setsrv2 ; ne = no
test flags.remflg,dserver ; acting as a server now?
jz setsrv3 ; z = no
stc ; fail
ret
setsrv3:mov bx,offset rdbuf ; where to store local username
mov dx,offset luserh ; help
mov comand.cmblen,16 ; buffer length
mov ah,cmword ; get username
call comnd
jc setsrvx
mov bx,offset rdbuf+30 ; where to store local password
mov dx,offset lpassh ; help
mov comand.cmblen,16 ; buffer length
mov comand.cmdonum,1 ; \number conversion allowed
mov ah,cmline ; get password, allow spaces
call comnd
jc setsrvx
mov si,offset rdbuf ; only now do we transfer to the
mov di,offset luser ; active buffers
call strcpy
mov si,offset rdbuf+30
mov di,offset lpass
call strcpy
clc
ret
setsrv2:mov min,0 ; Timeout, smallest acceptable value
mov max,255 ; largest acceptable value, one byte
mov numhlp,offset srvthlp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc setsrvx ; c = error
mov srvtmo,al ; store timeout value
clc ; success
setsrvx:ret
SETSRV ENDP
; Set REPEAT COUNTS {ON, OFF}
repset proc near
mov dx,offset setrep ; repeat table
xor bx,bx
mov ah,cmkey
call comnd
jnc repset1
ret
repset1:or bx,bx ; which item (counts, prefix)
jnz repset4 ; nz = prefix
mov dx,offset ontab ; on/off table
xor bx,bx ; use table for help
call keyend
jnc repset2 ; nc = success
ret
repset2:mov dtrans.rptqenable,bl ; repeat quote char enable/disable
ret
repset4:mov ah,cmword ; get a character
mov bx,offset rdbuf
mov rdbuf,defrptq ; default repeat prefix char
mov dx,offset prefhlp
call comnd
jc repset5 ; c = fail
push ax
mov ah,cmeol
call comnd
pop ax
jc repset5 ; c = fail
mov domath_ptr,offset rdbuf
mov domath_cnt,ax
mov domath_msg,1 ; no complaints
call domath ; convert numerics
jc repset6
mov rdbuf,al
repset6:mov al,rdbuf ; get char
call prechk ; check range
jc repset5 ; c = failed
mov dtrans.rptq,al ; set prefix
repset5:ret
repset endp
; Check if prefix in AL is in the proper range: 33-62, 96-126.
; Return carry clear if in range, else return carry set.
prechk proc near
cmp al,33
jb prechk2 ; b = out of range
cmp al,62
jbe prechk1 ; be = in range 33-62
cmp al,96
jb prechk2 ; b = out of range
cmp al,126
ja prechk2 ; a = out of range 96-126
prechk1:clc ; carry clear for in range
ret
prechk2:stc ; carry set for out of range
ret
prechk endp
; SET RETRY value. Changes the packet retry limit.
RETRYSET PROC NEAR
mov min,1 ; smallest acceptable value
mov max,63 ; largest acceptable value
mov numhlp,offset retryhlp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc retrys1 ; c = error
mov maxtry,al
retrys1:ret
RETRYSET ENDP
; Set number of screens in terminal emulator rollback buffer at Kermit
; initialization time via Environment. Called by command parser while doing
; Environment reading in mssker.asm. Do not call after Kermit has initialized.
SETROLLB proc near
mov numhlp,offset rollhlp ; help
mov numerr,0 ; no error message
mov min,0 ; smallest number
mov max,8000 ; largest magnitude
call num0 ; parse numerical input
jc setrol1 ; c = error
mov npages,ax ; store result
clc
setrol1:ret
SETROLLB endp
; Set width of rollback screens in terminal emulator rollback buffer at Kermit
; initialization time via Environment. Called by command parser while doing
; Environment reading in mssker.asm. Do not call after Kermit has initialized.
SETWIDTH proc near
mov rollwidth,80 ; default width of rolled screen
mov numhlp,0 ; no help
mov numerr,0 ; no error message
mov min,80 ; smallest number
mov max,207 ; largest magnitude (16 bits worth)
call num0 ; parse numerical input
jc setwid1 ; c = error
mov rollwidth,ax ; store result
clc
setwid1:ret
SETWIDTH endp
; SET TAKE ECHO or TAKE ERROR on or off
TAKSET PROC NEAR
mov dx,offset taketab ; Parse a keyword
xor bx,bx ; no specific help
mov ah,cmkey
call comnd
jnc takset1
ret ; failure
takset1:push bx ; save command indicator
mov dx,offset ontab
xor bx,bx
call keyend
pop ax ; recover command indicator
jnc takset2
ret ; failure
takset2:or al,al ; Take Echo command?
jnz takset3 ; nz = no
mov flags.takflg,bl
clc
ret
takset3:mov takeerror,bl ; Take Error command
clc
ret
TAKSET ENDP
; SET TIMER on or off during file transfer
TIMSET PROC NEAR
mov dx,offset ontab
xor bx,bx
call keyend
jc timset1 ; c = failure
mov flags.timflg,bl
timset1:ret
TIMSET ENDP
; SET WINDOW number of windows
WINSET PROC NEAR
mov min,1 ; smallest acceptable value
mov max,maxwind ; largest acceptable value
mov numhlp,offset winhelp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc winse5 ; c = error
mov dtrans.windo,al ; store default window size
mov trans.windo,al ; and in active variable for makebuf
clc ; success
winse5: ret
WINSET ENDP
; SET SEND parameters
SENDSET PROC NEAR
mov stflg,'S' ; Setting SEND parameter
mov dx,offset stsrtb ; Parse a keyword
xor bx,bx ; no specific help
mov ah,cmkey
call comnd
jc sendset1 ; c = failure
jmp bx ; do the action routine
sendset1:ret
SENDSET ENDP
; SET RECEIVE parameters
recset: mov stflg,'R' ; Setting RECEIVE paramter
mov dx,offset stsrtb ; Parse a keyword
xor bx,bx ; no specific help
mov ah,cmkey
call comnd
jc recset1 ; c = failure
jmp bx ; do the action routine
recset1:ret
remset proc near ; Set REMOTE ON/OFF
mov dx,offset ontab
mov bx,offset remhlp
call keyend
jc remset2 ; c = failure
and flags.remflg,not (dquiet+dserial+dregular) ; no display bits
or bl,bl ; want off state? (same as regular)
jz remset1 ; z = yes
or flags.remflg,dquiet ; else on = quiet display
clc
ret
remset1:or flags.remflg,dregular ; off = regular display
clc
remset2:ret
remset endp
; SET Send and Receive End-of-Packet char
sreol PROC NEAR
mov min,0 ; lowest acceptable value
mov max,1FH ; largest acceptable value
mov numhlp,offset eophlp ; help message
mov numerr,0 ; error message address
call num0 ; get numerical input
jc sreol3 ; c = error
cmp stflg,'S' ; setting SEND paramter?
je sreol1
mov trans.reol,al
jmp short sreol2
sreol1: mov dtrans.seol,al
sreol2: mov ah,dtrans.seol
mov trans.seol,ah
clc
sreol3: ret
sreol ENDP
; SET SEND and RECEIVE start-of-header
srsoh: mov min,0
mov max,7eh ; allow printables (control=normal)
mov numhlp,offset sohhlp ; reuse help message
mov numerr,0 ; error message
call num0 ; Common routine for parsing numerical input
jc srsoh2 ; c = error
cmp stflg,'S' ; setting SEND paramter?
je srsoh1
mov trans.rsoh,al ; set Receive soh
clc ; success
ret
srsoh1: mov trans.ssoh,al ; set Send soh
clc ; success
ret
srsoh2: ret
; SET Send Double-char
srdbl PROC NEAR
mov min,0 ; lowest acceptable value
mov max,0ffh ; largest acceptable value
mov numhlp,offset dblhlp ; help
mov numerr,0 ; error message address
call num0 ; get numerical input
jc sreol3 ; c = error
cmp stflg,'R' ; setting Receive paramter?
je srdbl1 ; e = yes, no action
mov trans.sdbl,al ; store character to be doubled
mov dtrans.sdbl,al
clc
srdbl1: ret
srdbl ENDP
; SET Receive Ignore-char
srign PROC NEAR
mov min,0 ; lowest acceptable value
mov max,0ffh ; largest acceptable value
mov numhlp,offset dblhlp ; reuse help
mov numerr,0 ; error message address
call num0 ; get numerical input
jc srign1 ; c = error
cmp stflg,'S' ; setting SEND paramter?
je srign1 ; e = yes, no action
mov trans.rign,al ; store character to be ignored
mov dtrans.rign,al
clc
srign1: ret
srign ENDP
; SET SEND and RECEIVE TIMEOUT
srtim: mov min,0
mov max,94
mov numhlp,offset timhlp ; Reuse help message
mov numerr,0 ; error message
call num0 ; Common routine for parsing numerical input
jc srtim3 ; c = error
cmp stflg,'S' ; Setting SEND paramter?
je srtim1
mov trans.rtime,al
jmp short srtim2
srtim1: mov dtrans.stime,al
srtim2: mov ah,dtrans.stime
mov trans.stime,ah
clc
srtim3: ret
; SET SEND and RECEIVE PACKET LENGTH
; dtrans items are real, trans items are just for SHOW information
srpack: mov min,20
mov max,9024
mov numhlp,offset pakhlp ; help
mov numerr,offset pakerr ; error message
call num0
jnc srpaks0 ; nc = success
ret ; failure
srpaks0:cmp stflg,'S' ; setting send value?
jne srpakr ; ne = receive
mov dtrans.slong,ax ; set send max value
mov trans.slong,ax ; store current active length
mov dtrans.spsiz,dspsiz ; set regular 94 byte default
mov trans.spsiz,dspsiz ; ditto
cmp ax,dspsiz ; longer than regular packet?
jae srpaks1 ; ae = yes
mov dtrans.spsiz,al ; shrink regular packet size too
mov trans.spsiz,al ; shrink regular packet size too
srpaks1:clc ; success
ret
srpakr: mov dtrans.rlong,ax ; set receive max value
mov trans.rlong,ax ; store active length
mov dtrans.rpsiz,drpsiz ; set regular to default 94 bytes
mov trans.rpsiz,drpsiz
mov trans.rpsiz,drpsiz
cmp ax,drpsiz ; longer than a regular packet?
jae srpakr1 ; ae = yes
mov dtrans.rpsiz,al ; shrink regular packet size too
mov trans.rpsiz,al
srpakr1:clc ; success
ret
; SET SEND and RECEIVE number of padding characters
srnpd: mov min,0
mov max,94
mov numhlp,offset timhlp ; reuse help message
mov numerr,0 ; error message
call num0 ; Parse numerical input
jc srnpd3 ; c = error
cmp stflg,'S' ; Setting SEND paramter?
je srnpd1 ; e = yes
mov trans.rpad,al ; set Receive padding
jmp short srnpd2
srnpd1: mov dtrans.spad,al ; set default Send padding
srnpd2: mov al,dtrans.spad
mov trans.spad,al ; update active array for I and S pkts
clc
srnpd3: ret
; SET SEND and RECEIVE padding character
srpad: mov min,0
mov max,127
mov numhlp,offset padhlp
mov numerr,offset padhlp
call num0 ; parse numerical input
jc srpad4 ; c = error
cmp ah,127 ; this is allowed
je srpad1
cmp ah,32
jb srpad1 ; between 0 and 31 is OK too
mov ah,prstr
mov dx,offset padhlp
int dos
srpad1: cmp stflg,'S' ; Send?
je srpad2 ; e = yes, else Receive
mov trans.rpadch,al ; store receive pad char
jmp short srpad3
srpad2: mov dtrans.spadch,al ; store Send pad char
srpad3: mov ah,dtrans.spadch
mov trans.spadch,ah ; update active array for I and S pkts
clc ; success
srpad4: ret
; SET SEND and RECEIVE control character prefix
srquo: mov min,33
mov max,126
mov numhlp,offset quohlp ; help message
mov numerr,0 ; error message
call num0 ; Parse numerical input
jc srquo3 ; c = error
cmp stflg,'S' ; Setting outgoing quote char?
je srquo1 ; e = yes
mov trans.rquote,al ; set Receive quote char
jmp short srquo2
srquo1: mov dtrans.squote,al ; set Send quote char
srquo2: clc
srquo3: ret
; SET SEND Pause number of milliseconds
srpaus: mov min,0
mov max,65383
mov numhlp,offset pauhlp ; help
mov numerr,0
call num0 ; Parse numerical input
pushf ; save carry for error state
cmp stflg,'S' ; Setting SEND paramter?
je srpau0
popf
mov dx,offset ermes5 ; "Not implemented" msg
jmp reterr ; print error message
srpau0: popf
jc srpau1 ; c = error
mov spause,ax ; store value
srpau1: ret
; SET RECEIVE REMOTE-PATH {enable, disable}
srpath proc near
mov dx,offset ontab
mov bx,offset rspathhlp
call keyend
jc srpath1
cmp stflg,'R' ; Setting RECEIVE paramter?
jne srpath1 ; ne = no
mov rcvpathflg,bl ; update receive flag
clc
ret
srpath1:mov sndpathflg,bl ; update send flag
clc
srpath2:ret
srpath endp
; Set stop-bits
stopbit proc near
mov min,1
mov max,2
mov numhlp,offset stophlp ; help
mov numerr,0
call num0 ; Parse numerical input
jnc stopbit1
ret ; c = failure
stopbit1:mov bx,portval
mov [bx].stopbits,al ; stop bits
clc
ret
stopbit endp
; SET TCP/IP address nnn.nnn.nnn.nnn
; SET TCP/IP subnetmask nnn.nnn.nnn.nnn
; SET TCP/IP gateway nnn.nnn.nnn.nnn
; SET TCP/IP primary-nameserver nnn.nnn.nnn.nnn
; SET TCP/IP secondary-nameserver nnn.nnn.nnn.nnn
; SET TCP/IP domain string
ifndef no_tcp
tcpipset proc near
mov ah,cmkey ; get keyword
mov dx,offset tcptable ; table
xor bx,bx ; help
call comnd
jnc tcpse1
ret
tcpse1: mov word ptr rdbuf,bx ; keyword index
mov comand.cmblen,17 ; length of user's buffer
cmp bx,1 ; local address?
jne tcpse1a ; ne = no
mov dx,offset addrhelp ; address help
jmp short tcpse4
tcpse1a:cmp bx,2 ; domain name?
jne tcpse2 ; ne = no
mov dx,offset domainhlp ; domain help
mov comand.cmblen,32 ; length of user's buffer
jmp short tcpse4
tcpse2: cmp bx,3 ; subnet mask?
jne tcpse3 ; ne = no
mov dx,offset subnethlp
jmp short tcpse4
tcpse3: cmp bx,7 ; Host?
jne tcpse3a ; ne = no
mov dx,offset hosthlp
mov comand.cmblen,60 ; length of user's buffer
jmp short tcpse4
tcpse3a:cmp bx,9 ; PD interrupt?
jne tcpse3b ; ne = no
mov dx,offset tcppdinthlp
jmp short tcpse4
tcpse3b:cmp bx,10 ; term type?
jne tcpse3c ; ne = no
mov dx,offset tcpttyhlp
mov comand.cmblen,32 ; length of user's buffer
jmp short tcpse4
tcpse3c:cmp bx,11 ; newline mode?
jne tcpse3d ; ne = no
jmp tcpse13
tcpse3d:cmp bx,12 ; debug mode?
jne tcpse3e ; ne = no
jmp tcpse14
tcpse3e:cmp bx,13 ; binary/nvt mode?
jne tcpse3f ; ne = no
jmp tcpse15
tcpse3f:cmp bx,14 ; MSS?
jne tcpse3g ; ne = no
jmp tcpse16
tcpse3g:mov dx,offset iphelp ; Internet number help
tcpse4: mov ah,cmword ; get a string
mov bx,offset rdbuf+2 ; work buffer
call comnd
jnc tcpse5
ret
tcpse5: push ax ; save string length in ax
mov ah,cmeol
call comnd
pop ax
jnc tcpse6
ret
tcpse6: mov si,offset rdbuf+2 ; user's string
mov bx,word ptr rdbuf ; comand kind
cmp bx,2 ; domain?
jne tcpse8 ; ne = no
mov di,offset tcpdomain
cmp ax,32 ; exceeded 32 chars?
jbe tcpse7 ; be = no
mov ah,prstr
mov dx,offset domainbad ; compain
int dos
stc
ret
tcpse7: cmp ax,32 ; address oversized?
jbe tcpse9 ; be = no
mov ah,prstr
mov dx,offset addressbad ; say bad address
int dos
stc
ret
tcpse8: mov di,offset tcpaddress
cmp bx,1 ; local address?
je tcpse9 ; e = yes
mov di,offset tcpsubnet
cmp bx,3 ; subnet?
je tcpse9 ; e = yes
mov di,offset tcpgateway
cmp bx,4 ; gateway?
je tcpse9
mov di,offset tcpprimens
cmp bx,5 ; primary-nameserver?
je tcpse9
mov di,offset tcpsecondns ; secondary-nameserer
cmp bx,6
je tcpse9
mov di,offset tcphost ; host name or number
cmp bx,7
je tcpse9
mov di,offset tcpbcast ; broadcast
tcpse9: cmp bx,9 ; port or other?
jae tcpse10 ; ae = yes
call strcpy
clc
ret
tcpse10:cmp bx,9 ; PD interrupt?
jne tcpse12 ; ne = no
mov si,offset rdbuf+2
tcpse11:mov ax,word ptr [si]
and ax,not 2020h ; to upper case
cmp ax,'DO' ; ODI?
je tcpse11a ; e = yes, use "DO"
push bx
mov domath_ptr,si
mov domath_cnt,16
call domath ; convert to number in ax
pop bx
tcpse11a:mov tcppdint,ax
clc
ret
tcpse12:cmp bx,10 ; term-type string?
jne tcpse13 ; ne = no
mov si,offset rdbuf+2
mov di,offset tcpttbuf ; copy string to holding place
call strcpy
clc
ret
tcpse13:cmp bx,11 ; newline mode?
jne tcpse14 ; ne = no
mov dx,offset newlinetab ; newline table
mov bx,offset tcpnlhlp ; help
call keyend
jc tcpse20 ; fail
mov tcpnewline,bl ; set mode
clc
ret
tcpse14:cmp bx,12 ; debug mode?
jne tcpse15 ; ne = no
mov dx,offset ontab ; on/off table
xor bx,bx ; help
call keyend
jc tcpse20 ; fail
mov tcpdebug,bl ; set mode
clc
ret
tcpse15:cmp bx,13 ; binary/nvt mode?
jne tcpse16 ; ne = no
mov dx,offset tcpmodetab ; mode table
xor bx,bx ; help
call keyend
jc tcpse20
mov tcpmode,bl ; set mode
clc
ret
tcpse16:cmp bx,14 ; MSS?
jne tcpse20 ; ne = no
mov numhlp,offset tcpmsshlp ; help
mov min,16 ; get decimal value
mov max,1460 ; range is 16 to 1460 decimal
mov numerr,0 ; error message
call num0 ; convert number, return it in ax
jc tcpse20 ; c = error
mov tcpmss,ax ; MSS
clc
ret
tcpse20:stc ; fail
ret
tcpipset endp
endif ; no_tcp
; SET TRANSFER CHARACTER-SET {Latin1, Shift-JIS, Transparent}
; SET TRANSFER TRANSLATION {Readable, Invertible}
; SET TRANSFER MODE {Automatic, Manual}
sxfer proc near
mov dx,offset xfertab ; table of TRANSFER keywords
xor bx,bx
mov ah,cmkey ; get next keyword
call comnd
jc sxfer1 ; c = error
or bl,bl ; Character-set?
jnz sxfer2 ; nz = no
mov dx,offset xfchtab ; Character-set table
mov bx,offset xfchhlp ; help text
call keyend
jc sxfer1 ; c = error
mov dtrans.xchset,bl ; store transfer char set ident
mov trans.xchset,bl ; store transfer char set ident
cmp bl,xfr_cyrillic ; Cyrillic?
jne sxfer9 ; ne = no
mov ax,flags.chrset ; get current file character set
mov flags.chrset,866 ; force CP866
cmp ax,866 ; was CP866/LATIN5 File Character set?
je sxfer8 ; e = yes
mov dx,offset xfchbad ; show warning message
mov ah,prstr
int dos
sxfer8: clc
sxfer1: ret
sxfer9: cmp bl,xfr_japanese ; Japanese-EUC?
jne sxfer10 ; ne = no
mov ax,flags.chrset ; get current file character set
mov flags.chrset,932 ; force Shift-JIS
cmp ax,932 ; was Shift-JIS File Character set?
je sxfer8 ; e = yes
mov dx,offset xfchbad2 ; show warning message
mov ah,prstr
int dos
clc
ret
sxfer10:cmp bl,xfr_hebiso ; Hebrew-ISO?
jne sxfer8 ; ne = no
mov ax,flags.chrset ; get current file character set
mov flags.chrset,862 ; force CP 862
cmp ax,862 ; was CP862 the File Character set?
je sxfer8 ; e = yes
mov dx,offset xfchbad3 ; show warning message
mov ah,prstr
int dos
clc
ret
sxfer2: cmp bx,1 ; LOCKING-SHIFT?
jne sxfer3 ; ne = no
mov dx,offset xfertab1 ; off, on, forced table
mov bx,offset xferhlp1
call keyend
jc sxfer1
mov dtrans.lshift,bl ; save state
mov trans.lshift,bl
clc
ret
sxfer3: cmp bx,2 ; Translation table?
jne sxfer4 ; ne = no
mov dx,offset xfertab2 ; TRANSLATION table
mov bx,offset xfchhlp2 ; help text
call keyend
jc sxfer1 ; c = error
mov dtrans.xchri,bl ; store readable/invertible flag
mov trans.xchri,bl
clc
ret
sxfer4: mov dx,offset xfertab3 ; MODE table
mov bx,offset xferhlp3 ; help text
call keyend
jc sxfer1 ; c = error
mov dtrans.xmode,bl ; store file transfer mode sensing
mov trans.xmode,bl
clc
ret
sxfer endp
; SET TRANSLATION Connect mode translate characters
; SET TRANSLATION INPUT {Original-byte New-byte | ON | OFF}
; SET TRANSLATION KEYBOARD {ON | OFF}, default is ON
SETRX PROC NEAR ; translate incoming serial port char
mov ah,cmkey
mov dx,offset trnstab ; direction table (just one entry)
xor bx,bx ; no help
call comnd
jnc setrx0 ; nc = success
ret ; failure
setrx0: cmp bx,2 ; Keyboard?
jne setrx0b ; ne = no
jmp setr11 ; do keyboard
setrx0b:mov bx,offset rdbuf ; our work space
mov dx,offset srxhlp1 ; first help message
mov ah,cmword ; parse a word
call comnd ; get incoming byte pattern
jnc setrx0a ; nc = success
ret
setrx0a:or ax,ax ; any text given?
jz setr6 ; nz = no
mov temp,ax ; save byte count here
mov ax,word ptr rdbuf ; get first two characters
or ax,2020h ; convert upper to lower case
cmp ax,'fo' ; first part of word OFF?
je setr6 ; e = yes, go analyze
cmp ax,'no' ; word ON?
je setr6 ; e = yes, go do it
mov domath_ptr,offset rdbuf
mov domath_cnt,16
mov domath_msg,1 ; stop messages
call domath ; convert to number in ax
jnc setr1 ; nc = success
mov ax,word ptr rdbuf
cmp temp,1 ; just one character given?
;;;;;;; jne setr6 ; ne = no, so bad code
setr1: mov min,ax ; save byte code here
mov bx,offset rdbuf ; our work space
mov dx,offset srxhlp1 ; first help message
mov ah,cmword ; parse a word
call comnd ; get incoming byte pattern
jnc setr2 ; nc = success
ret ; failure
setr2: or ax,ax ; any text given?
jz setr6 ; z = no
mov temp,ax ; save byte count here
mov domath_ptr,offset rdbuf
mov domath_cnt,ax
mov domath_msg,1 ; stop messages
call domath ; convert to number in ax
jnc setr3 ; nc = success
mov ax,word ptr rdbuf
cmp temp,1 ; just one character given?
;;;;; jne setr6 ; ne = no, so bad code or ON/OFF
setr3: mov max,ax ; save byte code here
mov ah,cmeol ; get a confirm
call comnd
jnc setr3a ; nc = success
ret ; failure
setr3a: mov bx,min ; bl = incoming byte code
xor bh,bh
mov ax,max ; al = local (translated) byte code
mov rxtable [bx],al ; store in rx translate table
clc ; success
ret
setr6: mov ah,cmeol ; get a confirm
call comnd
jnc setr6a ; nc = success
ret ; failure
setr6a: mov dx,offset badrx ; assume bad construction
or word ptr rdbuf,2020h ; convert to lower case
or rdbuf+2,20h ; first three chars
cmp word ptr rdbuf,'fo' ; key word OFF?
jne setr8 ; ne = no
cmp rdbuf+2,'f' ; last letter of OFF?
jne setr8 ; ne = no
mov rxtable+256,0 ; OFF is status byte = zero
mov dx,offset rxoffmsg ; say translation is turned off
jmp short setr9
setr8: cmp word ptr rdbuf,'no' ; keyword ON?
jne setr9a ; ne = no, error
mov rxtable+256,1 ; ON is status byte non-zero
mov dx,offset rxonmsg ; say translation is turned on
setr9: cmp taklev,0 ; executing from a Take file?
je setr9a ; e = no
cmp flags.takflg,0 ; echo contents of Take file?
je setr10 ; e = no
setr9a: mov ah,prstr ; bad number message
int dos
setr10: clc
ret
setr11: mov ah,cmkey ; SET TRANSLATION KEYBOARD
mov dx,offset ontab ; on/off
xor bx,bx
call comnd
jnc setr12 ; nc = success
ret
setr12: push bx
mov ah,cmeol ; get a confirm
call comnd
pop bx
jnc setr13 ; nc = success
ret ; failure
setr13: mov flags.xltkbd,bl ; set keyboard translation on/off
clc
ret
SETRX ENDP
; SET TRANSMIT {FILL, LF, Prompt} {ON, OFF, or value}
SETXMIT proc near
mov dx,offset xmitab ; TRANSMIT keyword table
xor bx,bx
mov ah,cmkey ; get keyword
call comnd
jnc setxmi1 ; nc = success
ret
setxmi1:cmp bl,2 ; SET TRANSMIT PROMPT?
jne setxmi2 ; ne = no
mov ah,cmword
mov bx,offset rdbuf ; put answer here
mov dx,offset xpmthlp
call comnd
jc setxmi1d ; c = error
push ax ; save length
mov ah,cmeol ; get a confirm
call comnd
pop cx ; recover length to cx
jc setxmi1d ; c = failure
mov al,rdbuf
cmp cx,1 ; a single char?
je setxmi1c ; e = yes, use it as the prompt char
mov domath_ptr,offset rdbuf
mov domath_cnt,cx
call domath ; convert to number in ax
jc setxmi1d ; c = no number, error
setxmi1c:mov script.xmitpmt,al ; store new prompt value
setxmi1d:ret
setxmi2:cmp bl,1 ; LF?
jne setxmi3 ; ne = no
mov dx,offset ontab ; on or off table
xor bx,bx
call keyend
jc setxmi2a ; c = failure
mov script.xmitlf,bl ; set the xmitlf flag
setxmi2a:ret
setxmi3:cmp bl,0 ; FILL?
jne setxmi8 ; ne = no
mov ah,cmword ; FILL, get a word sized token
mov bx,offset rdbuf ; put it here
mov dx,offset xfilhlp ; help
call comnd
jc setxmix ; c = failure
push ax ; save length in ah
mov ah,cmeol ; get a confirm
call comnd
pop ax
jc setxmix ; c = failure
cmp ax,1 ; just one character?
ja setxmi4 ; a = no, there's more
mov al,rdbuf ; get the char
mov script.xmitfill,al ; store Fill char
ret
setxmi4:mov ax,word ptr rdbuf
or ax,2020h ; to lower
cmp ax,'on' ; "none"?
jne setxmi5 ; ne = no
mov script.xmitfill,0 ; no Filling
ret
setxmi5:cmp ax,'ps' ; "space"?
jne setxmi6 ; ne = no
mov script.xmitfill,' ' ; use space as filler
ret
setxmi6:mov domath_ptr,offset rdbuf
mov domath_cnt,17
call domath ; convert to number in ax
jc setxmix ; c = no number, error
mov script.xmitfill,al ; set the xmitfill flag
ret
setxmi8:mov ah,cmword ; PAUSE milliseconds
mov bx,offset rdbuf ; put answer here
mov dx,offset xpauhlp
call comnd
jc setxmix ; c = error
push ax ; save length
mov ah,cmeol ; get a confirm
call comnd
pop cx ; recover length to cx
jc setxmix ; c = failure
mov domath_ptr,offset rdbuf
mov domath_cnt,cx
call domath ; convert to number in ax
jc setxmix ; c = no number, error
mov script.xmitpause,ax ; set the xmitpause flag
setxmix:ret
SETXMIT endp
; SET UNKNOWN-CHARACTER-SET {DISCARD, KEEP}, default is KEEP
unkchset proc near
mov dx,offset unkctab ; keep/reject keyword table
mov bx,offset unkchhlp
call keyend
jc unkchx ; c = failure
mov flags.unkchs,bl ; 0 = keep, else reject
unkchx: ret
unkchset endp
; Common routine for parsing numerical input
; Enter with numhlp = offset of help message, numerr = offset of optional
; error message, min, max = allowable range of values.
; Returns value in ax, or does parse error return.
; Changes ax,bx,dx,si. [jrd] 18 Oct 1987
num0: mov bx,offset rdbuf ; where to put text
mov dx,numhlp ; help text
mov ah,cmword ; get a word
call comnd
push ax ; save string count
mov ah,cmeol
call comnd ; Get a confirm
pop ax
jc num0x ; c = failure
call numwd
num0x: ret
; second entry point
; routine to print an error message, then exit without error status
; expects message in dx
reterr proc near
mov ah,prstr
int dos
clc
ret
reterr endp
code ends
code1 segment
; Add an entry to a keyword table
; enter with bx = table address, dx = ptr to new entry, macptr = string seg,
; mccptr = offset of free bytes in table mcctab.
; no check is made to see if the entry fits in the table.
addtab proc far
push cx
push si
push es
push bp
cld
mov ax,ds
mov es,ax ; address data segment
mov bp,bx ; remember where macro name table starts
mov cl,[bx] ; pick up length of table
xor ch,ch
inc bx ; point to actual table
jcxz addta4 ; cx = 0 if table is presently empty
addta1: push cx ; preserve count
mov si,dx ; point to entry
lodsw ; get length of new entry
mov cx,[bx] ; and length of table entry
cmp ax,cx ; are they the same?
lahf ; remember result of comparison
jae addta2 ; is new smaller? ae = no, use table length
mov cx,ax ; else use length of new entry
addta2: lea di,[bx+2] ; point to actual keyword
repe cmpsb ; compare strings
pop cx ; restore count
jb addta4 ; below, insert before this one
jne addta3 ; not below or same, keep going
sahf ; same. get back result of length comparison
jb addta4 ; if new len is smaller, insert here
jne addta3 ; if not same size, keep going
mov si,bx ; else this is where entry goes
jmp short addta6 ; no insertion required
addta3: mov ax,[bx] ; length of keyword
add bx,ax ; skip this entry
add bx,4 ; length word and 16 bit value
loop addta1 ; and keep looking
addta4: mov si,bx ; this is first location to move
mov di,bx
inc ds:byte ptr [bp] ; remember we're adding one
jcxz addta6 ; z = no more entries, forget this stuff
addta5: mov bx,[di] ; get length
lea di,[bx+di+4] ; end is origin + length + 4 for len, value
loop addta5 ; loop thru remaining keywords
mov cx,di
sub cx,si ; compute # of bytes to move
push si ; preserve loc for new entry
mov si,di ; first to move is last
dec si ; minus one
mov di,dx ; new entry
mov bx,[di] ; get length
lea di,[bx+si+4] ; dest is source + length of new + 4
std ; move backward
rep movsb ; move the table down (compress it)
cld ; put flag back
pop si
addta6: mov di,si ; this is where new entry goes
mov si,dx ; this is where it comes from
mov cx,[si] ; length of name
add cx,2 ; include count byte
add mccptr,cx ; update free space pointer: cnt+name
rep movsb ; insert new entry
mov ax,macptr ; and string address
stosw
add mccptr,2 ; plus string address
pop bp
pop es
pop si
pop cx
ret
addtab endp
; If new keyword matches an existing one then remove existing keyword,
; its string definition, compress tables mcctab and macbuf, readjust string
; pointers for each macro name, reduce number of macro table entries by one.
; Enter with DI pointing at length word of mac name (followed by mac name).
; Otherwise, exit with no changes. 13 June 1987 [jrd]
remtab proc far
push ax
push bx
push cx
push si
push di
push temp ; preserve
mov bx,offset mcctab+1 ; table of macro keywords
mov temp,0 ; temp = current keyword
cmp byte ptr mcctab,0 ; any macros defined?
jne remta1 ; ne = yes
jmp remtax ; else exit now
remta1: ; match table keyword and text word
mov si,di ; pointer to user's cnt+name
mov cx,[si] ; length of user's macro name
jcxz remtax ; empty macro name to remove
add si,2 ; point to new macro name
cmp cx,[bx] ; compare length vs table keyword
jne remta4 ; ne = not equal lengths, try another
push si ; lengths match, how about spelling?
push bx
add bx,2 ; point at start of keyword
remta2: mov ah,[bx] ; keyword char
mov al,[si] ; new text char
cmp al,ah ; test characters
jne remta3 ; ne = no match
inc si ; move to next char
inc bx
loop remta2 ; loop through entire length
remta3: pop bx
pop si
jcxz remta6 ; z: cx = 0, exit with match;
; else select next keyword
remta4: inc temp ; number of keyword to test next
mov cx,temp
cmp cl,mcctab ; all done? Recall, temp starts at 0
jb remta5 ; b = not yet
jmp remtax ; exhausted search, unsuccessfully
remta5: mov ax,[bx] ; cnt (keyword length from macro)
add ax,4 ; skip count and word pointer
add bx,ax ; bx = start of next keyword slot
jmp short remta1 ; do another comparison
; new name already present as a macro
remta6: cld ; clear macro string and macro name
push ds
pop es ; set es to data segment
mov temp,bx ; save ptr to found keyword
mov ax,[bx] ; cnt (keyword length of macro)
add ax,2 ; skip cnt
add bx,ax ; point to string segment field
add ax,2 ; count segment field bytes
sub mccptr,ax ; readjust free space ptr for names
push bx
push es
mov es,[bx] ; segment of string
mov ax,ds ; check for being in our data segment
cmp ax,[bx] ; same as our data seg?
je remta7 ; e = yes, don't free that
mov ah,freemem ; free that memory block
int dos
remta7: pop es
pop bx
; clear keyword table mcctab
add bx,2 ; compute source = next keyword
mov si,bx ; address of next keyword
mov di,temp ; address of found keyword
mov cx,offset mcctab+mcclen ; address of buffer end
sub cx,si ; amount to move
jcxz remtax ; cx = 0 means none
rep movsb ; move down keywords (deletes current)
dec mcctab ; one less keyword
remtax: pop temp ; recover temp variable
pop di
pop si
pop cx
pop bx
pop ax
ret
remtab endp
; Renames macros \%0..\%9 by changing the first two characters of the name
; to be <null><taklev>. Used to preserve old \%n macros and not show them.
; Return carry set if nothing is hidden.
hidemac proc far
push bx
push cx
push temp
mov byte ptr temp,'0' ; start with this \%0 name
hidema1:mov bx,offset mcctab+1 ; table of macro names, skip count
mov cl,mcctab ; number of entries
xor ch,ch
jcxz hidema6 ; z = empty table
hidema2:cmp word ptr [bx],3 ; name length, do three byte names
jne hidema3 ; ne = not three chars
cmp word ptr [bx+2],'%\' ; starts with correct prefix?
jne hidema3 ; ne = no
mov al,byte ptr [bx+4] ; third char of name
cmp al,byte ptr temp ; matches name?
je hidema4 ; e = yes
hidema3:mov ax,[bx] ; get length of name
add ax,4 ; plus count and word pointer
add bx,ax ; point to next entry
loop hidema2
jmp short hidema5
hidema4:call hidewrk ; call worker to hide macro
hidema5:inc byte ptr temp
cmp byte ptr temp,'9' ; all done?
jbe hidema1 ; be = no
hidema6:pop temp
pop cx
pop bx
ret
hidemac endp
; Hide existing macro. Enter with BX pointing to entry slot in mcctab,
; uses settemp as temp workspace.
; Used by hidemac and localmac.
hidewrk proc far
push bx
push cx
push si
push di
mov di,bx ; need di for remtab
mov ax,[bx] ; original count word
mov cx,ax
add ax,2 ; plus new prefix
mov si,offset settemp
mov [si],ax ; len = old length plus <null><level>
xor al,al ; prepare new prefix
mov ah,taklev ; of <null><taklev>
mov [si+2],ax ; new prefix
add si,4 ; count and prefix
hidewr1:mov al,[bx+2] ; copy old name after prefix
mov [si],al
inc bx
inc si
loop hidewr1
mov bx,di
mov ax,[bx] ; length of name
add ax,2 ; plus name length count word
add bx,ax ; point at definition segment
mov ax,1 ; smallest allocation
call malloc ; allocate space as dummy definition
mov cx,[bx] ; seg of original def to CX
mov [bx],ax ; seg of dummy def replaces it
call remtab ; remove macro, di is pointer
mov macptr,cx ; tell addtab definition segment
mov bx,offset mcctab ; macro name table
mov dx,offset settemp ; new name
call addtab ; create new entry for <null><digit><oldname>
pop di
pop si
pop cx
pop bx
ret
hidewrk endp
; Removes all current \%0..\%9 macros and renames <null><taklev> macros by
; removing the first two characters of the names of form <null><taklev>foo.
; Used to recover old \%n macros from hidemac and locals from Local.
unhidemac proc far
push bx
push cx
push dx
push di ; do rename of <null><taklev>foo
unhide1:mov di,offset mcctab+1 ; table of macro names, skip count
mov cl,mcctab ; number of entries
xor ch,ch
jcxz unhide5 ; z = empty table
xor dl,dl ; dx = macro prefix to examine
mov dh,taklev ; di => length word, name string
unhide2:cmp word ptr [di+2],dx ; starts with <null><taklev> prefix?
jne unhide4 ; ne = no
mov bx,di
mov cx,[bx] ; length of definition
sub cx,2 ; skip prefix bytes
push si
mov si,offset settemp ; destination work buffer
mov [si],cx ; new length
add si,2 ; have stored count word
add bx,2+2 ; skip count word and prefix
unhide3:mov al,[bx]
mov [si],al ; copy name to temp array
inc si
inc bx
loop unhide3
pop si
mov bx,di
add bx,[bx] ; skip macro name
add bx,2 ; and count word
mov cx,[bx] ; cx is now seg of definition
mov ax,1 ; minimal allocation of one byte
call malloc ; create dummy def
mov [bx],ax ; write new dummy def segment
call remtab ; remove prefixed name, DI is ptr
mov di,offset settemp ; shortened name
call remtab ; remove unprefixed macro, DI is ptr
mov bx,offset mcctab ; mac table
mov dx,offset settemp ; name string
mov macptr,cx ; segment of definition
call addtab ; add to table
jmp short unhide1
unhide4:mov ax,[di] ; get length of name
add ax,4 ; plus count and word pointer
add di,ax ; point to next entry
loop unhide2 ; look at next entry
unhide5:pop di
pop dx
pop cx
pop bx
ret
unhidemac endp
numwd proc far ; worker
mov domath_ptr,offset rdbuf
mov domath_cnt,ax
call domath ; convert to number in ax
jc num0er ; c = no number, error
cmp ax,max ; largest permitted value
ja num0er ; a = error
cmp ax,min ; smallest permitted value
jb num0er ; b = error
clc
ret ; return value in ax
num0er: mov dx,numerr ; comand-specific error message, if any
or dx,dx ; was any given?
jz num0e1 ; z = no, use generic msg
push ds
mov ax,seg data1 ; where help lives
mov ds,ax
mov ah,prstr
int dos ; show given error message
pop ds
jmp short num0e2
num0e1: mov dx,offset nummsg1 ; get address of numeric error message
push ds
mov ax,seg data1
mov ds,ax
mov ah,prstr
int dos
pop ds
mov ax,min ; smallest permitted number
call decout ; display decimal number in ax
mov ah,prstr
push ds
mov dx,seg nummsg2
mov ds,dx
mov dx,offset nummsg2 ; "and"
int dos
pop ds
mov ax,max ; largest permitted number
call decout
mov ah,prstr
mov dx,offset crlf
int dos
num0e2: stc
ret
numwd endp
; Worker for POP/END and RETURN.
; Pop take levels (via takclo) through tails of For/While, back to the
; take level of the last DO or prompt command.
POPLEVEL proc far
cmp taklev,0 ; in a Take/macro?
je poplevx ; e = no
mov bx,takadr
mov al,[bx].takinvoke ; take level of last DO or command
mov ah,[bx].takattr ; attributes
cmp taklev,al ; Take level now versus last DO
jb poplevx ; b = have exited macro already
push ax
call takclos ; close current Macro/Take
pop ax
test ah,take_while+take_subwhile ; closed While/For/Switch?
jz poplevx ; z = no
mov bx,takadr
test [bx].takattr,take_while+take_subwhile ; for/while macro?
jnz poplevel ; nz = yes, exit for/while too
poplevx:clc
ret
POPLEVEL endp
FDECLARE proc far ; declare array \&<char @a..z>[size]
or ax,ax ; null entry?
jnz decl2
stc ; fail
ret
decl2: cmp rdbuf[3],'&' ; syntax checking
jne declf ; ne = fail
cmp rdbuf[5],'[' ; size bracket?
jne declf ; ne = no, fail
and rdbuf[4],not 20h ; to upper case
mov al,rdbuf[4] ; array name
cmp al,'A' ; range check
jb declf
cmp al,'Z'
ja declf
mov si,offset rdbuf[6] ; point at size number
xor ah,ah
mov cx,128 ; limit scan
decl3: lodsb
cmp al,']' ; closing bracket?
je decl4 ; e = yes
inc ah ; count byte
loop decl3 ; keep looking
jmp declf ; fail if got here
decl4: xor al,al
xchg ah,al
sub si,ax ; point at start of number
dec si
mov domath_ptr,si
mov domath_cnt,ax
call domath ; convert to number in ax
jnc decl5 ; nc = success, value is in DX:AX
ret ; fail
decl5: or dx,dx ; too large a value?
jnz decl5a ; nz = yes
cmp ax,32000 ; 32000 max
jbe decl5b ; be = in range
decl5a: mov dx,offset arraybad ; say too large
mov ah,prstr
int dos
jmp declf ; fail
decl5b: mov bl,rdbuf[4]
sub bl,'@' ; remove bias
js declf ; s = sign, failure
xor bh,bh ; preserve bx til end of proc
shl bx,1 ; address words
call decl20 ; call remover
cmp ax,0 ; index of zero to clear the array?
je decl6 ; e = yes, done
inc ax ; create one more than [value]
call decl10 ; call creator
decl6: ret
declf: stc ; failure
ret
decl20 proc near ; remove array
push ax ; save size in ax
push es
mov si,marray[bx] ; get segment of array's definition
or si,si ; anything present?
jz decl23 ; no, no need to undefine anything
mov es,si
mov cx,es:[0] ; get number of elements
jcxz decl23 ; z = none, unlikely
xor si,si ; count word (number of elements)
decl21: add si,2 ; point to slot holding string seg
mov ax,es:[si] ; get string seg
or ax,ax ; null?
jz decl22 ; z = yes, ignore
mov word ptr es:[si],0 ; clear string seg pointer
push es
mov es,ax ; segment
mov ah,freemem ; free the memory
int dos
pop es
decl22: loop decl21
xor ax,ax ; get a zero
xchg ax,marray[bx] ; clear array seg storage pointer
mov es,ax
mov ah,freemem ; free storage pointer memory
int dos
decl23: pop es
pop ax
clc ; end removing array
ret
decl20 endp
decl10 proc near ; creator
push ax ; save ax
inc ax ; number of elements plus one size int
shl ax,1 ; count bytes for malloc
call malloc ; get seg of memory to ax
pop cx ; array size (was in ax)
jc decl12 ; c = failed
mov marray[bx],ax ; remember storage area
push es
push di
mov es,ax ; segment of new memory
mov es:[0],cx ; write size of array as 1st word
mov di,2 ; offset of string seg pointers
xor ax,ax
cld
rep stosw ; clear the array
pop di
pop es
clc
decl12: ret ; can return carry set from failure
decl10 endp
FDECLARE endp
; define contents of array element. Command line is in rdbuf+2 as
; \&<char>[index] definition, from dodef. Length of line is in cx.
defarray proc far
cmp rdbuf[3],'&' ; syntax checking
jne defarf ; ne = fail
cmp rdbuf[5],'[' ; size bracket?
jne defarf ; ne = no, fail
and rdbuf[4],not 20h ; to upper case
mov al,rdbuf[4] ; array name
cmp al,'A' ; range check
jb defarf
cmp al,'Z'
ja defarf
mov si,offset rdbuf[6] ; point at size number
xor ah,ah
cld
defar3: lodsb
cmp al,']' ; closing bracket?
je defar4 ; e = yes
inc ah ; count byte
loop defar3 ; keep looking
jmp defarf ; fail if got here
defar4: xor al,al ; cx has chars remaining in cmd line
xchg ah,al
mov di,si ; save di as start of definition space
sub si,ax ; point at start of number
dec si
mov domath_ptr,si
mov domath_cnt,ax
call domath ; do string to binary dx:ax
jnc defar5 ; nc = success, value is in DX:AX
ret ; fail
defar5: mov temp,ax ; save index value
mov bl,rdbuf[4] ; get array name letter
sub bl,'@' ; remove bias
xor bh,bh ; preserve bx til end of proc
shl bx,1 ; address words
defar6: call defar_rem ; clear current definition, if any
inc di ; skip space between name and def
mov dx,di ; for strlen
call strlen ; length of definition
jcxz defar7 ; z = no definition, done
mov ax,cx ; bytes needed
add ax,2+2 ; starts with byte count and elem 0
call malloc ; get the space
jc defarf ; c = failed
mov si,marray[bx] ; segment of array
or si,si ; if any
jz defar7 ; z = none
push es
mov es,si
mov si,temp ; array index
shl si,1 ; index words
mov es:[si+2],ax ; remember segment of string def
mov es,ax ; string definition seg
mov es:[0],cx ; length of string
mov si,di ; start of string text
mov di,2 ; destination
cld
rep movsb ; copy to malloc'd space
pop es
defar7: clc ; success
ret
defarf: mov kstatus,ksgen ; general command failure
stc ; failure exit
ret
; Remove string definition. Enter with BX holding array name index, and
; TEMP holding array index.
defar_rem proc near ; remove definition of array element
push ax ; undefining string within array
push si
push es
mov ax,marray[bx] ; current array seg
or ax,ax ; if any
jz defar_rem1 ; z = none
mov si,temp ; index value
shl si,1 ; index words
mov es,ax
mov ax,es:[0] ; get array size
shl ax,1 ; in words
cmp si,ax ; index versus size
ja defar_rem1 ; a = out of bounds, ignore
xor ax,ax ; get a zero
xchg ax,es:[si+2] ; get string's segment to ax, clr ref
or ax,ax ; anything there?
jz defar_rem1 ; z = no
mov es,ax ; seg to es for DOS
mov ah,freemem ; free string space
int dos
defar_rem1:
pop es
pop si
pop ax
ret
defar_rem endp
defarray endp
; Revise string in ES:SI et seq. Expect incoming length to be in CX.
; Original string modified to replace bare commas with Carriage Returns.
; Top level braces removed, but only if the string begins with an
; opening brace, and hence commas revealed are also converted to CR.
; A null is forced at the end of the string.
; All registers preserved except CX (returned length).
docnv proc far
push ax
push bx
push dx
push si ; src domacptr:0,2
push di
xor bx,bx ; brace count (bl), paren (bh)
mov dl,braceop ; opening brace (we count them up)
mov dh,bracecl ; closing brace (we count them down)
mov cx,es:[si] ; get string length
jcxz docnv9 ; z = empty
add si,2 ; where text starts
mov di,si ; si = source
cld
mov ah,es:[si] ; record opening char
docnv2: mov al,es:[si] ; read a char
cmp al,dl ; opening brace?
jne docnv3 ; ne = no
inc bl ; count brace level
cmp bl,1 ; first level?
jne docnv7 ; ne = no, write intact
or bh,bh ; in parens?
jnz docnv7 ; nz = yes, don't replace
cmp ah,dl ; started with opening brace?
jne docnv7 ; ne = no, don't replace brace
jmp short docnv8 ; skip opening brace
docnv3: cmp al,dh ; closing brace?
jne docnv4 ; ne = no
dec bl ; count down
or bl,bl ; still within braces?
jg docnv7 ; g = yes, write intact
xor bx,bx ; found brace match, reset to zero
cmp ah,dl ; started with opening brace?
jne docnv7 ; ne = no, write brace
jmp short docnv8 ; omit the brace
docnv4: cmp al,'(' ; opening paren?
jne docnv5 ; ne = no
inc bh ; count paren level
jmp short docnv7
docnv5: cmp al,')' ; closing paren?
jne docnv6 ; ne = no
dec bh
cmp bh,0 ; below 0?
jg docnv7 ; g = no, still in paren
xor bh,bh ; in case underrun, reset to zero
jmp docnv7 ; matching paren
docnv6: cmp al,',' ; comma?
jne docnv7 ; ne = no
or bh,bh ; in paren clause?
jnz docnv7 ; nz = yes, treat comma as literal
cmp bl,1 ; in braced clause?
ja docnv7 ; a = yes, treat comma as literal
mov al,CR ; replace bare comma with CR
docnv7: mov es:[di],al
inc di ; next destination byte
docnv8: inc si ; next input byte
loop docnv2 ; do more
docnv9: mov cx,di ; ending place + 1
pop di
pop si ; start of buffer
sub cx,si
sub cx,2 ; minus count word
mov es:[si],cx ; string length
pop dx
pop bx
pop ax
clc
ret
docnv endp
code1 ends
end