home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR8
/
VMAC111.ZIP
/
VMAC.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-08-05
|
82KB
|
2,127 lines
;███████████████████████████████████████████████████████████████████████████████
; VMAC.ASM (Version 1.11)
; Macro Compiler for Eric Meyer's VDE (Versions 1.53-1.65 and 1.70+)
;
; Source code for assembly under WASM, the Wolfware Assembler, by Eric Tauck.
;
; Author: Richard Cowell
; Address: S.K. Heights #6
; Suwa 239, Takatsu-ku
; Kawasaki, Kanagawa 213
; JAPAN
;███████████████████████████████████████████████████████████████████████████████
;=======================================
;[ INITIALIZATION ]
mov dx,DTA ; set DTA
mov ah,1Ah
int 21h
mov si,081h ; check command line
SkipSpaces
lodsb
cmp al,' '
jz SkipSpaces
jb Usage
cmp al,'/' ; if start of pathname
jnz Go ; jump
lodsb ; else al = option
Option
cmp al,'7'
jz Seven
and al,CAPMASK
cmp al,'U'
jnz Usage
or Flag,USEDONLY
jmps AnyMore
Seven
or Flag,VERSION170
AnyMore
lodsb
cmp al,' '
jz SkipSpaces
ja Option
Usage
mov si,offset Umsg
call Puts
;---------------------------------------;
TheEnd ;
int 20h ;
;---------------------------------------;
Go
dec si
mov pArg,si ; set pArg to start of filename
;=======================================
;[ MAIN LOOP ]
NextArg
call GetPath
jc TheEnd
test Flag,WILDCARD
jz Process
mov dx,PATH ; find first file
xor cx,cx ; attribute: ordinary files
mov ah,04Eh
int 21h
jnc WildLoop
mov si,offset XFfmsg ; "no matching files" message
call Puts
mov si,PATH
call Puts
call PutCrlf
jmps NextArg
WildLoop
mov si,DTANAME ; copy filename onto drive:\dir spec.
mov di,PATH
add di,DrivDirLen
mov cx,13
rep
movsb
Process
call Convert
test Flag,WILDCARD
jz NextArg
mov ah,04Fh ; find next file
int 21h
jnc WildLoop
jmps NextArg
;█████████████████████████████████ PROCEDURES ██████████████████████████████████
;╒══════════════════════════════════════╕
;│ GetPath │
;│ copies argument to PATH │
;│ if wildcard found: │
;│ WILDCARD flag set │
;│ DrivDirLen set │
;│ CF set if no more arguments │
;╘══════════════════════════════════════╛
GetPath PROC NEAR
mov si,pArg
lodsb
or al,al ; any arguments?
jnz Check_gp ; yes, go
stc ; no, set CF
ret
;=======================================
;[ find start of pathname ]
Skip_gp
lodsb
Check_gp
cmp al,' '
jz Skip_gp
mov bx,si
dec bx ; bx = start of pathname
;[ find end ]
Advance_gp
lodsb
cmp al,' '
ja Advance_gp
mov byte [si-1],0 ; make ASCIZ
mov dx,si ; save position for length calculation
jz Store_gp ; if al = space, jump
dec si ; else al = CR, move si back to 0
Store_gp
mov pArg,si ; store position for next call
;[ length ]
sub dx,bx
dec dx ; dx = length of pathname w/o 0
;[ capitalize and copy ]
mov si,bx ; si = start of pathname
mov cx,dx ; cx = length
mov di,PATH
Next_gp
lodsb
cmp al,'a'
jb Copy_gp
cmp al,'z'
ja Copy_gp
and al,CAPMASK
Copy_gp
stosb
loop Next_gp
movsb ; include terminal 0
;[ check for wildcards ]
and Flag,FIXEDFLAGS
mov DrivDirLen,0
mov si,PATH ; si = start of pathname
mov cx,dx ; cx = length
AstQuest_gp
lodsb
cmp al, '*'
jz Wild_gp
cmp al,'?'
jz Wild_gp
loop AstQuest_gp
jmps Ret_gp
;=======================================
Wild_gp
or Flag,WILDCARD
;[ Check for drive\dir spec. ]
sub si,2 ; si points to char before wildcard
mov cx,si
sub cx,PATH - 1 ; cx = bytes to check
jle Ret_gp ; if negative or zero, no drive\dir
std ; direction = backward
Back_gp
lodsb
cmp al,'\'
jz DDLen_gp ; if '\' found, jump
cmp al,':'
jz DDLen_gp ; if ':' found, jump
loop Back_gp
DDLen_gp ; cx = 0 on fall-through
mov DrivDirLen, cx ; cx = number of bytes in driv\dir spec
cld
Ret_gp
clc
ret
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ MAIN ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;╒══════════════════════════════════════╕
;│ Convert │
;╘══════════════════════════════════════╛
Convert PROC NEAR
call OpenFile
jc Error_cnv
call ReadFile
jc Error_cnv
mov VDXbytes,0 ; count of mode+definition bytes
test Flag,VDKINPUT or VDFINPUT
jnz Macro_cnv
call TextToMac
jnc Output_cnv
jmps Error_cnv
Macro_cnv
call MacToText
jc Error_cnv
Output_cnv
call WriteBuff
jc Error_cnv
Flags_cnv
and Flag,FIXEDFLAGS OR WILDCARD
ret
;---------------------------------------
Error_cnv
call PutCrlf ; out: ah = 0Eh
test Flag,LINEERROR
jz ErrMsg_cnv
mov al,'<'
int 10h
mov si,PATH
call Puts
mov al,'>'
int 10h
call PutCrlf
mov si,pLine
call Puts
call PutCrlf
ErrMsg_cnv
mov si,dx
call Puts
test Flag,SHOWOVERFLOW
jz FileErr_cnv
mov ax,VDXBytes
call Putu
mov si,offset Bmsg
jmps Puts_cnv
FileErr_cnv
test Flag,FILEERROR
jz Ret_cnv
mov si,PATH
Puts_cnv
call Puts
Ret_cnv
call PutCrlf
jmps Flags_cnv
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ INPUT FILE ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;╒══════════════════════════════════════╕
;│ OpenFile │
;│ checks extension, opens file │
;│ │
;│ Out: CF clear, bx = handle │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
OpenFile PROC NEAR
;[ find start of extension ]
mov di,PATH
add di,DrivDirLen ; di = ptr to start of filename
mov cx,9 ; max. 8-byte filename + 1
mov al,'.' ; scan for period
repne
scasb
jnz Xx_opf ; if not found, error. jump
;[ check 1st characters ]
mov ax,[di] ; ax should contain 'VT' or 'VD'
inc di
mov pMidExt,di ; pMidExt points to 2nd char of extension
inc di ; di points to 3rd char of extension
cmp ax,'VT'
jz Text_opf
cmp ax,'VD'
jnz Xx_opf
;[ macro file .VDx ]
cmp byte [di],'K'
jnz VDF_opf
or Flag,VDKINPUT ; VDK
mov Indent,INDENTVTK
jmps Open_opf
VDF_opf
cmp byte [di],'F'
jnz Xx_opf
or Flag,VDFINPUT ; VDF
mov Indent,INDENTVTF
jmps Open_opf
;[ text file .VTx ]
Text_opf
cmp byte [di],'K'
jnz VTF_opf
or Flag,VTKINPUT ; VTK
jmps Open_opf
VTF_opf
cmp byte [di],'F' ; VTF
jnz Xx_opf
or Flag,VTFINPUT ; CF clear
;[ open file ]
Open_opf
mov dx,PATH ; dx = ptr to filename
mov ax,03D00h ; open file, read access (al = 0)
int 21h
jc Xo_opf ; jump on error
mov bx,ax ; out: bx = handle. CF clear.
ret
;---------------------------------------
Xx_opf
mov dx,offset XFxmsg
jmps X_opf
Xo_opf
mov dx,offset XFomsg ; "can't open" message
X_opf
or Flag,FILEERROR
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ ReadFile │
;│ reads input file into buffer and │
;│ closes file │
;│ │
;│ In: bx = handle │
;│ Out: Bytes = bytes read to buffer │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
ReadFile PROC NEAR
mov dx,VDXBUFFER ; address of buffer
mov cx,VDXSIZE ; bytes available
test Flag,VDFINPUT OR VDKINPUT
jnz Read_rdf
mov dx,TEXTBUFFER ; address of buffer
mov cx,TEXTSIZE ; bytes available
Read_rdf
mov bp,cx ; save buffer size in bp
mov ah,03Fh ; read file (bx = handle)
int 21h
jc Xr_rdf ; jump on error
or ax,ax
jz Xr_rdf ; if no bytes read, error. jump
mov Bytes,ax ; store bytes read
cmp ax,bp ; is buffer completely full?
jz Xl_rdf ; yes, file is too large. jump
clc
;[ close file ]
Close_rdf
pushf
mov ah,03Eh ; (bx = handle)
int 21h
popf
ret
;---------------------------------------
Xl_rdf
mov dx,offset XFlmsg ; "too large to handle" message
jmps X_rdf
Xr_rdf
mov dx,offset XFrmsg ; "read problem" message
X_rdf
or Flag,FILEERROR
stc
jmps Close_rdf
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ MACRO --> TEXT ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;╒══════════════════════════════════════╕
;│ MacToText │
;│converts .VDF or .VDK file in VDXBUFFR│
;│to text in TEXTBUFFER │
;│ │
;│ Out: di = limit of data in TEXTBUFFER│
;│ Err: CF set, dx = error message │
;│ │
;│ Important registers: │
;│ si = ptr to macro file in VDXBUFFER│
;│ di = ptr to text in TEXTBUFFER │
;│ bp = ptr to table of key names │
;│ In macro loop: │
;│ dx = length of key name │
;│ In def loop: │
;│ dl = length of key name │
;│ dh = line length │
;│ cx = bytes remaining in def │
;│ al = byte of def │
;╘══════════════════════════════════════╛
MacToText PROC NEAR
;=======================================
;[ I. check file ID ]
mov si,VDXBUFFER
lodsw
cmp ax,FILEID153
jz Go_mtt
cmp ax,FILEID170
jz Check_mtt
mov dx,offset XFimsg
or Flag,FILEERROR
stc
ret
;=======================================
;[ II. initialization ]
Check_mtt
call ChekLabel ; sets ISLABEL Flag and Indent if label
Go_mtt
mov di,TEXTBUFFER ; di = destination
test Flag,VDFINPUT
jnz VDF_mtt
mov bp,offset CharKeys ; initialize ptr to key name table
mov dx,CHARKEYLENGTH ; length of key name
mov pKeyLimit,CHARKEYLIMIT ; limit of table
jmps MacStart_mtt
VDF_mtt
mov bp,offset FuncKeys ; initialize ptr to key name table
mov dx,FUNCKEYLENGTH ; length of key name
mov pKeyLimit,NRMFUNCLIMIT ; limit of table
jmps MacStart_mtt
;=======================================
;[ III. macro loop ]
AddCRLF_mtt
mov ax,CRLF ; write CRLF
stosw
xor dh,dh ; dx = length of key name
NextMac_mtt
add bp,dx ; advance ptr to next name in table
cmp bp,pKeyLimit ; end of table?
jz CheckFunc_mtt ; yes, jump.
;------------------------------
MacStart_mtt
;[A. length ]
lodsb ; al = definition length
or al,al ; definition exists?
jnz KeyName_mtt ; yes, jump to write name
test Flag,USEDONLY ; write used key names only?
jnz NextMac_mtt ; yes, jump back
; no, write all names
;[B. key name ]
KeyName_mtt
mov ah,al ; save length of definition in ah
call WriteKey
mov cl,ah
xor ch,ch ; cx = bytes in definition
jcxz AddCRLF_mtt ; if none, jump
inc cx ; include mode byte in count
add VDXBytes,cx ; update byte count for display
dec cx
;[C. label ]
lodsb
mov dh,al ; dh = macflag: mode+autoexec+label bits
test Flag,ISLABEL
jz Mode_mtt
call WritLabel
;[D. mode ]
Mode_mtt
mov bl,dh
and bx,MODEBITS
add bx,offset Mode ; [bx] = space, Q, N, or B
test dh,AUTOEXEC
jz NoAuto_mtt
mov al,'A'
mov ah,[bx]
jmps StoMode_mtt
NoAuto_mtt
mov al,[bx]
mov ah,' '
StoMode_mtt
stosw
;[E. equal sign ]
mov ax,'= '
stosw
;[F. definition ]
call WriteDef
jmps AddCRLF_mtt
;=======================================
CheckFunc_mtt ; see if F11,F12,etc. need to be shown
cmp bp,NRMFUNCLIMIT
jnz Ret_mtt
cmp word [si],0 ; F11, F12
jnz ShowExt_mtt
cmp word [si+2],0 ; !F11,!F12
jnz ShowExt_mtt
cmp word [si+4],0 ; ^F11,^F12
jnz ShowExt_mtt
cmp word [si+6],0 ; @F11,@F12
jz Ret_mtt
ShowExt_mtt
mov pKeyLimit,EXTFUNCLIMIT
jmps MacStart_mtt
Ret_mtt
clc
ret
ENDP
;╒══════════════════════════════════════╕
;│ ChekLabel │
;│ If .VDF file has any labels: │
;│ sets ISLABEL Flag │
;│ resets Indent │
;│ │
;│ In: si = VDXBUFFER+2: start of macros│
;╘══════════════════════════════════════╛
ChekLabel PROC NEAR
xor ah,ah
mov cx,FUNCKEYNUMB
Go_cl
lodsb ; al = length w/o flag byte
or al,al
jz Loop_cl
test byte [si],LABELBIT ; si points to flag byte
jnz Flag_cl ; if label, jump to set Flag
add si,ax ; else go to next macro
Loop_cl
loop Go_cl
Ret_cl
mov si,VDXBUFFER+2 ; si = start of macros
ret
;=======================================
Flag_cl
or Flag,ISLABEL
mov Indent,INDENTVTFLBL
jmps Ret_cl
ENDP
;╒══════════════════════════════════════╕
;│ WriteKey │
;│ In: ah = definition length │
;│ bp = ptr to key name │
;│ di = ptr to TEXTBUFFER │
;│Preserves: si, dl │
;╘══════════════════════════════════════╛
WriteKey PROC NEAR
mov al,'['
stosb
test Flag,VDFINPUT
jnz FuncKey_wk
;[ character key ]
mov al,[bp]
stosb
xor cx,cx
jmps RghBraket_wk
;[ function key ]
FuncKey_wk
mov bx,si ; save si in bx
mov si,bp ; si = ptr to key name
mov cx,4 ; cx = max. length of name
NextChar_wk
lodsb
or al,al
jz Restore_wk
stosb
loop NextChar_wk
Restore_wk
mov si,bx ; restore ptr to VDXBUFFER in si
RghBraket_wk
mov al,']'
stosb
or ah,ah ; definition exists?
jz Ret_wk ; no, jump
;[ write spaces ]
inc cx
mov al,' '
rep
stosb
Ret_wk
ret
ENDP
;╒══════════════════════════════════════╕
;│ WritLabel │
;│ In: dh = macro flag │
;│ si = ptr to byte after macro flag│
;│ di = ptr to text buffer │
;│ cx = bytes remaining in macro │
;│ Preserves: dl │
;╘══════════════════════════════════════╛
WritLabel PROC NEAR
mov bx,cx ; save macro length in bx
mov al,'<'
stosb
mov cx,7
test dh,LABELBIT
jz NoLabel_wrl
sub bx,cx ; adjust bytes remaining
rep ; copy label
movsb
jmps Done_wrl
NoLabel_wrl
mov al,' ' ; no label: write spaces
rep
stosb
Done_wrl
mov ax,'> '
stosw
mov cx,bx ; restore bytes remaining in macro in cx
ret
ENDP
;╒══════════════════════════════════════╕
;│ WriteDef │
;│ In: cx = bytes in definition │
;│ si = ptr to definition │
;│ di = ptr to TEXTBUFFER │
;│ dl = length of name │
;╘══════════════════════════════════════╛
WriteDef PROC NEAR
mov dh,Indent ; dh = bytes already written to line
jmps Space_wrd
;=======================================
;[--- new line of text ---]
NewLine_wrd
call NewLine
Space_wrd
cmp byte [si],' ' ; is first character a space?
jnz GetByte_wrd ; no, jump
mov byte [di],'`' ; yes, write special character (`)
inc di ; advance pointer
inc dh ; update line length
jmps GetByte_wrd ; jump
;=======================================
;[--- definition loop ---]
LineLeng_wrd
cmp dh,MAXLINELENGTH ; is this line already long enough?
jae NewLine_wrd ; yes, jump to wrap def to new line
GetByte_wrd
lodsb ; al = definition byte
;[<<DECISIONS>>]
cmp al,' ' ; al < space ?
jb Ctrl_wrd ; yes, control character. jump
cmp al,0FFh ; al = FFh ?
jz FF_wrd ; yes, jump
cmp al,'@' ; check for characters @ ^ `
jz AtCaretAcut_wrd
cmp al,'^'
jz AtCaretAcut_wrd
cmp al,'`'
jz AtCaretAcut_wrd
cmp al,07Fh ; ^BkSp?
jz CtrlBkSp_wrd
;-----------------------
;[ store one character ]
StoreByte_wrd
stosb ; write one byte
inc dh ; update line length
loop LineLeng_wrd ; loop back to get check line length
jmps EndDef_wrd
;----------------------------
;[ Special character: @ ^ ` ]
AtCaretAcut_wrd
mov byte [di],'`' ; write "no translation" character (`)
inc di ; advance pointer
inc dh ; update line length
jmps StoreByte_wrd ; jump to store character
;----------------------
;[ key names: "[xxxxx]" ]
FFSpecial_wrd
call FndKeyNam
jmps WriteName_wrd
CtrlBkSp_wrd
mov bx,offset CtrlBkSp
jmps WriteName_wrd
CtrlEsc_wrd
mov bx,offset CtrlEsc
jmps WriteName_wrd
Esc_wrd
mov bx,offset EscKey
WriteName_wrd
xchg bx,si ; save ptr to def in bx. si = name.
WriteNext_wrd
lodsb
stosb
inc dh
cmp al,']'
jnz WriteNext_wrd
mov si,bx ; restore ptr to definition in si
loop LineLeng_wrd ; loop back to check line length
jmps EndDef_wrd ; else jump to end processing
;----------
;[ <Ctrl> ]
Ctrl_wrd
cmp al,ESCAPE ; Esc?
jz Esc_wrd ; yes, jump to write '[Esc]'
mov ah,al ; change 1-->^A, 2-->^B, 3-->^C,....
add ah,'A'-1
mov al,'^'
stosw
add dh,2 ; update line length
loop LineLeng_wrd ; loop back to check line length
jmps EndDef_wrd ; else jump to end processing
;--------------------
;[ ASCII code = FFh ]
FF_wrd
lodsb ; get next byte
dec cx ; reduce bytes remaining
;[<<DECISIONS>>]
cmp al,LOWESTALTX
jb FFSpecial_wrd
cmp al,HIGHESTALTX
ja FFSpecial_wrd
cmp al,0AAh ; CtrlEsc ?
jz CtrlEsc_wrd ; yes, jump
call WriteAltX ; write '@X'
loop LineLeng_wrd ; loop back to check line length
; else fall through to end processing
;=======================================
;[--- end of definition ---]
EndDef_wrd
cmp byte [di-1],' ' ; does macro end with a space?
jz AddSpecial_wrd ; yes, jump
ret
AddSpecial_wrd
mov word [di-1],'` ' ; change space to "` " as visual aid
inc di ; advance pointer
ret
ENDP
;╒══════════════════════════════════════╕
;│ NewLine │
;│ wraps line in TEXTBUFFER │
;│ │
;│ In: di = ptr to TEXTBUFFER │
;│ Out: dh = bytes written to new line │
;│ Preserves: cx (bytes in definition) │
;│ dl (length of key name) │
;╘══════════════════════════════════════╛
NewLine PROC NEAR
mov bx,cx ; save bytes remaining in bx
;[ check end of current line for space ]
cmp byte [di-1],' ' ; does line end with a space?
jnz CRLF_nwl ; no, jump
mov word [di-1],'` ' ; yes, change to "` " as visual aid
inc di ; advance pointer
CRLF_nwl
mov ax,CRLF ; write CRLF
stosw
;[ set up indentation of new line ]
mov dh,Indent ; start of definition
mov cl,dh
xor ch,ch
sub cx,2 ; allow 2 bytes for '= '
mov al,' ' ; write spaces
rep
stosb
mov ax,'= '
stosw
mov cx,bx ; restore bytes remaining in cx
ret
ENDP
;╒══════════════════════════════════════╕
;│ WriteAltX │
;│ In: al = scan code for Alt + Letter │
;│ Out: writes '@X' to TEXTBUFFER │
;│ updates dh (line length) │
;│ Preserves: cx │
;╘══════════════════════════════════════╛
WriteAltX PROC NEAR
push cx
mov bx,di ; save ptr to TEXTBUFFER in bx
mov di,offset AltXScan ; scan table of scan codes
mov cx,ALTXNUMB
repne
scasb ; cx = reverse index into alphabet
mov di,bx ; restore ptr to TEXTBUFFER in di
mov bx,LASTLETTER ; bx = ptr to last letter of alphabet
sub bx,cx ; subtract index
mov ah,[bx] ; ah = letter
mov al,'@' ; al = '@'
stosw ; store in TEXTBuFF
add dh,2 ; update line length
pop cx
ret
ENDP
;╒══════════════════════════════════════╕
;│ FndKeyNam │
;│ In: al = scan code │
;│Out: bx = address of key name │
;│Preserves: cx,di │
;╘══════════════════════════════════════╛
FndKeyNam PROC NEAR
push cx
mov bx,di ; save ptr to TEXTBUFFER in bx
mov di,offset KeyCodes ; scan table of codes
mov cx,KEYCODENUMB
repne
scasb ; cx = reverse index into list of names
mov di,bx ; restore ptr to TEXTBUFFER in di
mov bx,LASTKEYNAME ; bx = ptr to last entry in name list
shl cx ; index --> offset (8 bytes/name)
shl cx
shl cx
sub bx,cx ; subtract offset
pop cx
ret
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ TEXT --> MACROS ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;╒══════════════════════════════════════╕
;│ TextToMac │
;│ converts text file in TEXTBUFFER to │
;│ macros in VDXBUFFER │
;│ │
;│ Out: di = limit of data in VDXBUFFER │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
TextToMac PROC NEAR
;[ initialization ]
test Flag,CAPITALIZED
jnz Init_ttm
call CapNames
Init_ttm
mov bx,VDXBUFFER ; bx = ptr to VDXBUFFER
mov pTextMark,TEXTBUFFER
mov ax,FILEID153
mov pMacLimit,MACLIMIT5
test Flag,VTKINPUT
jnz VTK_ttm
;[ function key macros ]
mov pKey,offset FuncKeys ; ptr to table of key names
mov pFindMacKy,offset FindFncKy ; ptr to search procedure
test Flag,VERSION170
jz Version_ttm
mov ax,FILEID170
mov pMacLimit,MACLIMIT7
jmps Version_ttm
VTK_ttm ;[ character key macros ]
mov pKey,offset CharKeys ; ptr to table of key names
mov pFindMacKy,offset FindChrKy ; ptr to search procedure
test Flag,VERSION170
jz Version_ttm
mov dx,offset XFvmsg
or Flag,FILEERROR
stc
ret
;---------------------------------------
Version_ttm
mov [bx],ax ; store version number in VDXBUFFER
add bx,2
;=======================================
;[ MAIN LOOP ]
Line_ttm
call GetLine ; get data line
jc Zero_ttm ; if none, done. jump
Find_ttm
call pFindMacKy ; out: si points to byte after name
jc Xn_ttm ; jump on error
call ModeLabel ; out: si points to 1st byte of def
jc Ret_ttm ; jump on error
or si,si ; does definition exist?
jz NoDef_ttm ; no, jump
Def_ttm
call TextToDef ; convert text to macro definition
jc Ret_ttm ; jump on error
Line2_ttm
call GetLine ; get next line
jc Copy_ttm ; if none, jump to copy current macro
cmp byte [si],'[' ; new macro key?
jz Copy_ttm ; yes, jump to copy current macro
inc si ; no, continuation. advance beyond '='
;[ continuation: find start of definition ]
call SkipSpace
jc Line2_ttm ; if end of line, get another one
dec si ; move back to start of definition
jmps Def_ttm ; jump to convert
;[ copy macro to VDXBUFFER]
Copy_ttm
call CopyMacro
jc Ret_ttm
or si,si ; end of text file?
jnz Find_ttm ; no, jump to process next macro
jmps Zero_ttm ; yes, zero out rest of VDXBUFFER
;[ no definition ]
NoDef_ttm
mov byte [bx],0 ; add 0 to VDXBUFFER
inc bx ; advance pointer
jmps Line_ttm
;[ zero out rest of file ]
Zero_ttm
mov di,bx ; bx = limit of data in VDXBUFFER
mov cx,VDXFILELIMIT ; = VDXBUFFER + 1024
sub cx,di ; cx = limit of file - limit of data
xor ax,ax ; write zeros
shr cx ; cx = words to write
rep
stosw
adc cx,0 ; do last byte if it exists
rep
stosb ; out: di = limit of data in VDXBUFFER
;[ final check for V1.70+ macros ]
test Flag,AUTOEXECSET or ISLABEL
jz Ret_ttm
test Flag,VTKINPUT ; .VTK file?
jnz Xk_ttm ; yes, error. jump
mov word [VDXBUFFER],FILEID170 ; set file ID in case /7 option
Ret_ttm ; wasn't specified
ret
;---------------------------------------
Xn_ttm
mov dx,offset XLnmsg
or Flag,LINEERROR
jmps X_ttm
Xk_ttm
mov dx,offset XFkmsg
or Flag,FILEERROR
X_ttm
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ CapNames │
;│ Makes capitalized key name table at │
;│ CAPKEYNAMES │
;╘══════════════════════════════════════╛
CapNames PROC NEAR
mov si,offset KeyNames
mov di,CAPKEYNAMES
mov cx,KEYNAMELENGTH * KEYNAMENUMB
Next_ntu
lodsb
cmp al,'a'
jb Store_ntu
cmp al,'z'
ja Store_ntu
and al,CAPMASK
Store_ntu
stosb
loop Next_ntu
or Flag,CAPITALIZED
ret
ENDP
;╒══════════════════════════════════════╕
;│ GetLine │
;│gets start of next data line, skipping│
;│ comment lines and blank lines │
;│puts 0 at limit of defintion, that is │
;│ changes line to ASCIZ string │
;│ │
;│ In: pTextMark = ptr to TEXTBUFFER │
;│ Bytes = bytes remaining │
;│ Out: si = pLine = ptr to next line │
;│ pTextMark = limit of line │
;│ Bytes updated │
;│ CF clear │
;│Else: if end of buffer, CF set & si=0 │
;╘══════════════════════════════════════╛
GetLine PROC NEAR
mov di,pTextMark ; starting place in TEXTBUFFER
mov cx,Bytes ; bytes remaining in TEXTBUFFER
;=======================================
;[ I. find start of next line ]
cmp di,TEXTBUFFER ; at beginning of buffer?
jz Skip_gtl ; yes, jump
;[ scan to next LF ]
Next_gtl
mov al,LF
repne
scasb
jcxz None_gtl ; if no more bytes, jump
;[ skip initial whitespace ]
Skip_gtl
cmp byte [di],' '
ja Check_gtl ; if [di] > ' ', jump to check
jb Inc_gtl ; if [di] < ' ' (CR,LF,Tab), jump to skip
mov al,' ' ; if [di] = ' ', scan past spaces
repe
scasb
jcxz None_gtl ; if no more bytes, done
dec di ; go back to 1st non-space character
inc cx ; update byte count
cmp byte [di],' ' ; is [di] a CR,LF or Tab?
ja Check_gtl ; no, jump to check
Inc_gtl
inc di
dec cx
jnz Skip_gtl
None_gtl
xor si,si
stc
ret
;[ check for comment ]
Check_gtl
cmp cx,3 ; less than 3 bytes left (i.e. "= x")
jb None_gtl ; yes, can't be any more macros. done
mov al,[di] ; dl = first character
cmp al,'[' ; '[' ?
jz Start_gtl ; yes, found start, jump
cmp al,'=' ; '=' ?
jnz Next_gtl ; no, it's a comment, try again
; yes, found start
;[ save start ]
Start_gtl
mov si,di ; out: si = ptr to line
mov pLine,si ; store start for writing error message
;=======================================
;[ II. find limit of line ]
;[ scan to next LF ]
mov al,LF
repne
scasb
jz LF_gtl ; if LF found, jump
;[ LF not found: end of buffer ]
cmp byte [di-1],EOF ; is EOF last character in buffer?
jnz Set_gtl ; no, jump
dec di ; yes, move back one byte to EOF
jmps Set_gtl
;[ LF found ]
LF_gtl
sub di,2 ; go back to CR
add cx,2 ; adjust remaining bytes
;=======================================
;[ III. set variables ]
Set_gtl
mov pTextMark,di ; store position for next call
mov Bytes,cx ; store remaining bytes
;=======================================
;[ IV. remove comments from end of line ]
mov cx,di ; di = limit of line
sub cx,si ; cx = limit - start = length
mov di,si ; di = start of line
mov al,';' ; look for ';'
Semi_gtl
repne
scasb
jcxz Done_gtl ; if end of line, done (di = mac limit)
cmp byte [di],';' ; found. next character = ';'?
jnz Semi_gtl ; no, go back and check some more
cmp byte [di-2],' ' ; byte before 1st ';' = space ?
jnz Semi_gtl ; no, go back and check some more
;[ found comment. find end of macro ]
sub di,2 ; di points to space
mov cx,di
sub cx,si ; cx = di - start = bytes to start - 1
mov al,' ' ; skip spaces
std ; go backward
repe
scasb
cld ; clear direction flag
inc di ; go forward to last non-space character
cmp byte [di],'`' ; is it a special character?
jnz Zero_gtl ; no, jump to put '0'
inc di ; yes, include 1 space
Zero_gtl
inc di
Done_gtl
mov byte [di],0 ; zero out limit of macro
clc
ret
ENDP
;╒══════════════════════════════════════╕
;│ FindChrKy │
;│ In: si = ptr to key name in TEXTBUFF│
;│ bx = ptr to VDXBUFFER │
;│ pKey = ptr to table of key names │
;│ │
;│ Out: si points to 1st byte after name│
;│ bx,pKey updated │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
FindChrKy PROC NEAR
lodsb
cmp al,'[' ; check left bracket
jnz X_fck
lodsb ; al = character key
cmp byte [si],']' ; check right bracket
jnz X_fck
inc si ; out: si points to byte after key name
mov di,pKey ; di = ptr into list of character keys
cmp al,'A' ; if number, jump
jb Next_fck
and al,CAPMASK ; capitalize letter
Next_fck
cmp di,CHARKEYLIMIT ; beyond last key?
jz X_fck ; yes, error
cmp al,[di]
jz Done_fck ; if found, done
inc di ; else advance di to next character key
mov byte [bx],0 ; add 0 to VDXBUFFER
inc bx ; advance pointer
jmps Next_fck
Done_fck
inc di ; advance di to next character key
mov pKey,di ; update pKey
clc
ret
;---------------------------------------
X_fck
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ FindFncKy │
;│ In: si = start of key name │
;│ bx = ptr to VDXBUFFER │
;│ pKey = ptr to table of key names │
;│ │
;│ Out: si = 1 byte after key name │
;│ bx,pKey updated │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
FindFncKy PROC NEAR
lodsb
cmp al,'[' ; check left bracket
jnz X_ffk
mov bp,si ; save start of target in bp
;[ capitalize 'f' if necessary ]
cmp byte [si],'f'
jz BigF_ffk
inc si
cmp byte [si],'f'
jnz Length_ffk
BigF_ffk
mov byte [si],'F'
;[ get length of key name from data line ]
Length_ffk
mov di,bp ; di = start of target
mov al,']' ; look for right bracket
mov cx,FUNCKEYLENGTH+1 ; max. name length + right bracket
repne
scasb
jnz X_ffk ; if no bracket, error. jump
neg cx
add cx,FUNCKEYLENGTH ; cx = length of name
cmp cx,1
jbe X_ffk ; if '[]' or '[x]', error
mov dx,cx ; save length in dx
mov ax,pKey ; ax = ptr to table of names
Next_ffk
cmp ax,EXTFUNCLIMIT ; beyond last name?
jz X_ffk ; yes, error
mov di,ax ; di = ptr to key name
add ax,FUNCKEYLENGTH ; advance ptr to next key
mov si,bp ; si = ptr to target name
mov cx,dx ; cx = bytes to check
repe
cmpsb
jz Check_ffk ; if found, jump to check
;[ add 0 to buffer ]
mov byte [bx],0
inc bx
jmps Next_ffk
Check_ffk ; check for mismatch of [xF1] against
cmp di,ax ; [xF10],[xF11],or [xF12]
jz Done_ffk ; if target was 4 characters long, OK
cmp byte [di],0 ; if not, di should point to 0.
jnz X_ffk
Done_ffk ; (CF clear if ZF set)
inc si ; move si past right bracket
mov pKey,ax ; store ptr to next name
ret
;---------------------------------------
X_ffk
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ SkipSpace │
;│ In: si = ptr to ASCIZ string │
;│Out: CF clear │
;│ al = non-space non-tab char │
;│ si = ptr to next byte │
;│ CF set if end of line │
;╘══════════════════════════════════════╛
SkipSpace PROC NEAR
lodsb
or al,al ; end of line?
jz STC_sksp ; yes, jump
cmp al,' ' ; space or tab?
jbe SkipSpace ; yes, try again
ret ; if al > ' ', CF clear
STC_sksp
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ ModeLabel │
;│ writes mode code to buffer. │
;│ writes label to buffer │
;│ initializes pMacMark │
;│ finds start of definition. │
;│ │
;│ In: si = one byte past key name │
;│ │
;│ Def exists: CF clear, si = start │
;│ No def: CF clear, si = 0 │
;│ Err: CF set, dx = error msg │
;╘══════════════════════════════════════╛
ModeLabel PROC NEAR
mov pMacMark,MACSTART1 ; initialize ptr to MACBUFFER
mov byte [MACFLAG],0 ; initialize macro flag
call SkipSpace
jc NoDef_gml ; if end of line, no definition. jump
;[ label ]
cmp al,'<'
jnz Mode_gml
call GetLabel
jc X_gml
call SkipSpace
jc NoDef_gml
;[ mode ]
Mode_gml
call GetMode
jc X_gml
or al,al ; if end of line, no definition
jz NoDef_gml
cmp al,' ' ; if space or tab....
ja Equals_gml
call SkipSpace ; ....skip
jc NoDef_gml
;[ equal sign ]
Equals_gml
cmp al,'='
jnz Xe_gml
;[ definition ]
call SkipSpace
jc NoDef_gml ; if end of line, no def. jump
dec si ; move back to start of definition
ret ; def exists: CF clear, si = start
;---------------------------------------
NoDef_gml
xor si,si ; no def: CF clear, si = 0
ret
;---------------------------------------
Xe_gml
mov dx,offset XLemsg
X_gml
or Flag,LINEERROR
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ GetLabel │
;│ In: si = first byte after '<' │
;│Out: si = first byte after '>' │
;│ pMacMark updated │
;│ ISLABEL flag set if label exists │
;╘══════════════════════════════════════╛
GetLabel PROC NEAR
xor cx,cx ; cl = characters, ch = spaces
mov di,si ; save start in di
Next_glb
lodsb
or al,al ; end of line?
jz X_glb ; yes, error. jump
cmp al,'>' ; end of label?
jz Length_glb ; yes, jump
inc cl ; count 1 character
js X_glb ; if sign, label is much too long
cmp al,' ' ; space?
jnz Next_glb ; no, jump
inc ch ; yes, count 1 space
jmps Next_glb
Length_glb
cmp cl,7
ja X_glb ; if over 7 bytes, too long. jump
cmp cl,ch ; if spaces = characters, no label
jz Ret_glb ; (CF clear if ZF set)
;[ label exists ]
or byte [MACFLAG],LABELBIT ; set macro flag
mov pMacMark,MACSTART2 ; update pointer into MACBUFFER
xor ch,ch
mov dx,cx ; save number of characters in dx
mov si,di ; si = start of label
mov di,MACSTART1 ; di = destination in MACBUFFER
rep ; copy label to buffer
movsb
mov cx,7 ; pad with spaces
sub cx,dx
mov al,' '
rep
stosb
inc si ; advance si past '>'
or Flag,ISLABEL ; (CF clear)
Ret_glb
mov pMacLimit,MACLIMIT7 ; set def length to 255 bytes just in
ret ; case /7 option wasn't specified
;---------------------------------------
X_glb
mov dx,offset XLlmsg
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ GetMode │
;│ In: al = character to check │
;│ si = ptr to next byte │
;│Out: al = first non-mode character │
;│ si = next byte │
;╘══════════════════════════════════════╛
GetMode PROC NEAR
xor ah,ah ; code: 0 for nothing
jmps Equals_gmd
NextMod_gmd
lodsb
or al,al
jz Ret_gmd
cmp al,' '
jz Store_gmd
Equals_gmd
cmp al,'='
jz Store_gmd
and al,CAPMASK
cmp al,'N'
jz N_gmd
cmp al,'Q'
jz Q_gmd
cmp al,'B'
jz B_gmd
cmp al,'A'
jnz Xm_gmd
test Flag,VTKINPUT
jnz Xy_gmd
test Flag,AUTOEXECSET
jnz Xx_gmd
or Flag,AUTOEXECSET
mov pMacLimit,MACLIMIT7 ; set macro length to 255 bytes in case
mov cl,AUTOEXEC ; /7 option wasn't specified
jmps SetMode_gmd
N_gmd
mov cl,NOREPEAT
jmps Test_gmd
Q_gmd
mov cl,QUIET
jmps Test_gmd
B_gmd
mov cl,BOTH
Test_gmd
test ah,cl ; already set?
jnz Xm_gmd ; yes, error. jump
SetMode_gmd
or ah,cl ; set ah
jmps NextMod_gmd
Store_gmd
or [MACFLAG],ah ; store code in MACBUFFER
Ret_gmd
clc
ret
;---------------------------------------
Xm_gmd
mov dx,offset XLmmsg
jmps X_gmd
Xx_gmd
mov dx,offset XLxmsg
jmps X_gmd
Xy_gmd
mov dx,offset XLymsg
X_gmd
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ TextToDef │
;│converts text to definition in MACBUFF│
;│ │
;│ In: si = ptr to text definition │
;│ pMacMark = ptr to MACBUFFER │
;│ Out: pMacMark updated, CF clear │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
TextToDef PROC NEAR
mov di,pMacMark ; di = ptr to MACBUFFER
Next_ttd
lodsb
;[<<DECISIONS>>]
or al,al ; end of line?
jz End_ttd ; yes, jump
cmp al,'^'
jz Ctrl_ttd
cmp al,'@'
jz Alt_ttd
cmp al,'`'
jz Spec_ttd
cmp al,'['
jz Name_ttd
;[ ordinary character ]
stosb
jmps Next_ttd
;[ '^' character ]
Ctrl_ttd
call StoreCtrl
jnc Next_ttd
jmps X_ttd
;[ '@' character ]
Alt_ttd
call StoreAlt
jnc Next_ttd
jmps X_ttd
;[ '`' character ]
Spec_ttd
lodsb
or al,al ; end of line?
jz Xc_ttd ; yes, error. jump
stosb
jmps Next_ttd
;[ key name: [xxxxx] ]
Name_ttd
call StoreName
jmps Next_ttd
End_ttd
cmp di,pMacLimit ; have exceeded max bytes/definition?
ja Xt_ttd ; yes, jump
mov pMacMark,di ; out: pMacMark = limit of data
clc
ret
;---------------------------------------
Xc_ttd
mov dx,offset XLcmsg ; "bad last character" message
jmps X_ttd
Xt_ttd
sub di,pMacLimit
mov VDXBytes,di ; amount of overflow for error message
mov dx,offset XLbmsg ; "too many bytes" message
or Flag,SHOWOVERFLOW
X_ttd
or Flag,LINEERROR
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ StoreCtrl │
;│ In: al = '^' │
;│ si = ptr to next byte in TEXTBUFF│
;│ di = ptr into MACBUFFER │
;╘══════════════════════════════════════╛
StoreCtrl PROC NEAR
lodsb
or al,al ; end of line?
jz Xc_stc ; yes, error. jump
sub al,'A'-1 ; ^A --> 1, ^B --> 2, etc.
jle Xd_stc ; if al <= 0, error. jump
cmp al,31
ja Xd_stc ; if al > 31, error. jump
stosb
clc
ret
;---------------------------------------
Xc_stc
mov dx,offset XLcmsg
jmps X_stc
Xd_stc
mov dx,offset XLdmsg
X_stc
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ StoreAlt │
;│ In: al = '@' │
;│ si = ptr to next byte in TEXTBUFF│
;│ di = ptr into MACBUFFER │
;╘══════════════════════════════════════╛
StoreAlt PROC NEAR
lodsb ; al = letter of alphabet (maybe)
or al,al ; end of line?
jz Xc_sta ; yes, error. jump
and al,CAPMASK ; capitalize
mov bp,di ; save position in MACBUFFER
mov di,offset Alphabet
mov cx,ALTXNUMB
repne
scasb
jnz Xa_sta
mov di,LASTALTXSCAN
sub di,cx
mov ah,[di]
mov al,0FFh
mov di,bp ; restore ptr to MACBUFFER in di
stosw
clc
ret
;---------------------------------------
Xc_sta
mov dx,offset XLcmsg
jmps X_sta
Xa_sta
mov dx,offset XLamsg
X_sta
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ StoreName │
;│ In: al = '[' │
;│ si = ptr to byte after '[' │
;│ di = ptr into MACBUFFER │
;╘══════════════════════════════════════╛
StoreName PROC NEAR
mov dx,di ; save ptr into MACBUFFER in dx
mov bp,si ; save ptr to text string in bp
;[ copy key name to SYMBUFFER ]
mov cx,KEYNAMELENGTH ; counter
mov di,SYMBUFFER
Sym_stn
stosb
dec cx
jz NoGo0_stn ; if max length already copied, jump
lodsb
or al,al ; end of line?
jz NoGo0_stn ; yes, not key name. jump.
cmp al,'[' ; start of key name?
jz NoGo0_stn ; yes, current can't be key name. jump
cmp al,']' ; end of key name?
jz EndName_stn ; yes, jump
cmp al,'a' ; capitalize
jb Sym_stn
cmp al,'z'
ja Sym_stn
and al,CAPMASK
jmps Sym_stn
EndName_stn
stosb ; save ']'
cmp cx,KEYNAMELENGTH - MINKEYLENGTH ; length too short?
ja NoGo0_stn ; yes, not key name. jump.
xor ax,ax
stosw ; pad SYMBUFFER with zeros
stosw
stosw
;[ binary search ]
push bx ; save ptr to VDXBUFFER
push dx ; save ptr to MACBUFFER
push si ; save current position in text string
push bp ; save original position in text string
call BinSearch
pop bp
pop si
pop di ; restore ptr to MACBUFFER in di
pop bx
jc NoGo_stn
cmp ah,080h ; ah < 80h only for Esc and ^BkSp
jb Other_stn
mov al,0FFh ; al = ASCII code for special key
stosw ; store ASCII:scan codes
ret
;---------------------------------------
Other_stn
mov al,ah ; ASCII code for Esc or ^BkSp
stosb
ret
;---------------------------------------
NoGo0_stn
mov di,dx ; restore pointer to MACBUFFER
NoGo_stn
mov al,'[' ; not a key name, store '['
mov si,bp ; restore original position in text
stosb
ret
ENDP
;╒══════════════════════════════════════╕
;│ BinSearch │
;│binary search procedure for key name │
;│ │
;│Found: │
;│ ah = scan code for special key, or │
;│ ASCII code for Esc or ^BkSp │
;│ CF clear │
;│Else: CF set │
;╘══════════════════════════════════════╛
BinSearch PROC NEAR
;[initialize bx,bp ]
mov bx,CAPKEYNAMES ; bx = left
mov bp,LASTCAPNAME ; bp = right
;[ check first element of symbol table ]
mov si,bx ; check left
mov di,SYMBUFFER ; di = ptr to target
mov cx,KEYNAMELENGTH ; cx = bytes to check
repe
cmpsb
jb Start_bs ; if left < target, jump to search
jz OK_bs ; if match, done
jmps NotFound_bs ; if target < left, not found
;[ search loop ]
Left_bs
mov bx,ax ; middle < target, so new left = middle
Start_bs
mov ax,bp ; ax = bp = right
Next_bs
sub ax,bx ; ax = right - left
cmp ax,KEYNAMELENGTH ; ax <= length of entry ?
jbe Last_bs ; yes, jump to last check
shr ax ; ax = (right-left)/2
and ax,0FFF8h ; round off to multiple of 8
add ax,bx ; ax = middle entry
mov si,ax ; check middle
mov di,SYMBUFFER ; di = ptr to target
mov cx,KEYNAMELENGTH ; cx = bytes to check
repe
cmpsb
jb Left_bs ; if middle < target, jump to set left
jz OK_bs ; if match, done
mov bp,ax ; target < middle, so new right = middle
jmps Next_bs
;[ final check on right ]
Last_bs
mov si,bp ; si = right
mov di,SYMBUFFER ; di = ptr to target
mov cx,KEYNAMELENGTH ; cx = bytes to check
repe
cmpsb
jnz NotFound_bs
OK_bs
sub si,8 ; si = ptr to matching key name
sub si,CAPKEYNAMES ; si = offset into array
shr si ; si/8 = index into array
shr si
shr si
add si,offset KeyCodes ; si = ptr into table of codes
mov ah,[si] ; ah = code
clc
ret
;---------------------------------------;
NotFound_bs
stc
ret
ENDP
;╒══════════════════════════════════════╕
;│ CopyMacro │
;│ copies macro in MACBUFFER to VDXBUFFR│
;│ │
;│ In: pMacMark = limit of macro │
;│ bx = ptr to VDXBUFFER │
;│ Out: bx updated, CF clear │
;│ Err: CF set, dx = error msg │
;│ │
;│ Preserves: si (ptr to next line) │
;╘══════════════════════════════════════╛
CopyMacro PROC NEAR
mov bp,si ; save si in bp
mov cx,pMacMark ; limit of data in MACBUFFER
sub cx,MACSTART1 ; length=limit - start of def (or label)
mov si,MACBUFFER ; start of macro
mov [si],cl ; store length
inc cx ; include mode byte
add VDXBytes,cx ; update count
cmp VDXBytes,VDXMACLIMIT ; have exceeded allowed bytes/file?
ja X_cpm ; yes, jump
inc cx ; include length byte for copy
mov di,bx ; destination in VDXBUFFER
rep
movsb
mov bx,di ; update position in VDXBUFFER
mov si,bp ; restore si
clc
ret
;---------------------------------------
X_cpm
sub VDXBytes,VDXMACLIMIT ; amount of overflow
mov dx,offset XLsmsg ; "maximum size exceeded" message
or Flag,LINEERROR or SHOWOVERFLOW
stc
ret
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ OUTPUT ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;╒══════════════════════════════════════╕
;│ WriteBuff │
;│ In: di = limit of data in buffer │
;│ Err: CF set, dx = error message │
;╘══════════════════════════════════════╛
WriteBuff PROC NEAR
mov si,pMidExt ; si points to middle letter of extension
test Flag,VDKINPUT or VDFINPUT
jz TextIn_wb
mov byte [si],'T' ; change VDx --> VTx
mov bp,TEXTBUFFER ; bp = buffer to write from
jmps Create_wb
TextIn_wb
mov byte [si],'D' ; change VTx --> VDx
mov bp,VDXBUFFER ; bp = buffer to write from
;[ create output file ]
Create_wb
mov dx,PATH
xor cx,cx ; ordinary attribute
mov ah,03Ch
int 21h
jc Xc_wb
mov bx,ax ; bx = handle
;[ write output ]
mov dx,bp ; dx = ptr to buffer
mov cx,di ; di = limit of data in buffer
sub cx,dx ; cx = limit - start = bytes to write
mov ah,040h
int 21h
pushf ; save flags
mov dx,ax ; save bytes written in dx
mov ah,03Eh ; close file
int 21h
popf
jc Xw_wb
cmp cx,dx ; bytes requested = bytes written?
jnz Xw_wb
call PutCrlf
mov si,PATH ; write filename
call Puts
mov si,offset Cmsg ; "created" message
call Puts
mov ax,VDXMACLIMIT ; write free space
sub ax,VDXBytes
call Putu
mov si,offset Fmsg ; "free bytes" message
call Puts
call PutCrlf
clc
ret
;---------------------------------------
Xc_wb
mov dx,offset XFcmsg
jmps X_wb
Xw_wb
mov dx,PATH
mov ah,041h ; delete file
int 21h
mov dx,offset XFwmsg
X_wb
or Flag,FILEERROR
stc
ret
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ STRING STUFF ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
;╒══════════════════════════════════════╕
;│ Puts │
;│ In: si = ptr to ASCIZ string │
;│ Out: ah = 0Eh │
;╘══════════════════════════════════════╛
Puts PROC NEAR
mov ah,0Eh
Next_pts
lodsb
or al,al
jz Done_pts
int 10h
jmps Next_pts
Done_pts
ret
ENDP
;╒══════════════════════════════════════╕
;│ PutCRLF │
;╘══════════════════════════════════════╛
PutCRLF PROC NEAR
mov ax,0E0Dh
int 10h
mov al,0Ah
int 10h
ret
ENDP
;╒══════════════════════════════════════╕
;│ PUTU │
;│ In: ax = unsigned number │
;│ Destroys: ax,bx,cx,dx │
;╘══════════════════════════════════════╛
PutU PROC NEAR
mov bx,10 ; going to divide by 10
xor cx,cx ; holds number of digits
Digit_ptu
xor dx,dx
div bx ; unsigned division ax/10 with rem in dx
push dx ; save on stack
inc cx ; count one digit
or ax,ax ; any more?
jnz Digit_ptu
Char_ptu
pop ax
add ax,0E30h ; TTY + '0'
int 10h
loop Char_ptu
ret
ENDP
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ DATA ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
; Format of output text files
; (M = mode = space, Q, N, or B)
; (A = AUTOEXEC for Version 1.70)
;--(1)--------------------------------------------------------
; === .VTK file ===
;
; [X] M = definition
; -->|8 byts|<--
INDENTVTK EQU 8
;--(2)--------------------------------------------------------
; === .VTF files: Vers.1.53 or Vers.1.70 with no labels ===
;
; [xFxx] M = definition
; [xFxx] AM= definition
; -->|11 bytes |<--
INDENTVTF EQU 11
;--(3)--------------------------------------------------------
; === .VTF files: Vers.1.70 with labels ===
;
; [xFxx] <LLLLLLL> M = definition
; [xFxx] <LLLLLLL> AM= definition
; |<-- 21 bytes -->|
INDENTVTFLBL EQU 21
;───────────────────────────────────────────────────────────────────────────────
FILEID153 EQU 5301h ; file ID for Version 1.53
FILEID170 EQU 7001h ; file ID for Version 1.70
MAXLINELENGTH EQU 72 ; wrap lines in text file longer than
; 72 characters since longest key name
; is 8 bytes long
;───────────────────────────────────────────────────────────────────────────────
;---- Word-Length Variables ----
Bytes dw ?
DrivDirLen dw 0
VDXBytes dw 0
pArg dw 81h ; current position on command line
pFindMacKy dw ? ; ptr to name finding procedure
pKey dw ? ; ptr into table of key names
pKeyLimit dw ? ; ptr to limit of table of key names
pLine dw ? ; ptr to start of data line in TEXTBUFFR
pMacLimit dw ? ; acceptable limit of macro in MACBUFFER
pMacMark dw ? ; ptr marking position in MACBUFFER
pMidExt dw ? ; ptr to middle character of extension
pTextMark dw ? ; ptr marking position in TEXTBUFFER
;───────────────────────────────────────────────────────────────────────────────
Flag dw 0
USEDONLY EQU 1b ; set with /U option
VERSION170 EQU 10b ; set with /7 option
CAPITALIZED EQU 100b ; set if key name table capitalized
WILDCARD EQU 1000b
VDFINPUT EQU 10000b ; set if input file is .VDF
VDKINPUT EQU 100000b ; set if input file is .VDK
VTFINPUT EQU 1000000b ; set if input file is .VTF
VTKINPUT EQU 10000000b ; set if input file is .VTK
ISLABEL EQU 100000000b
AUTOEXECSET EQU 1000000000b
FILEERROR EQU 10000000000000b
LINEERROR EQU 100000000000000b
SHOWOVERFLOW EQU 1000000000000000b
FIXEDFLAGS EQU USEDONLY OR VERSION170 OR CAPITALIZED
;───────────────────────────────────────────────────────────────────────────────
;--- Macro Flag ---
NOREPEAT EQU 01b
QUIET EQU 10b
BOTH EQU 11b
AUTOEXEC EQU 1000b
LABELBIT EQU 10000000b
MODEBITS EQU 11b
Mode db ' NQB'
;───────────────────────────────────────────────────────────────────────────────
;--- Byte-Length Variables ---
Indent db 0 ; number of columns prior to definition
; in output text file
;───────────────────────────────────────────────────────────────────────────────
;--- Character Codes ---
LF EQU 0Ah
CR EQU 0Dh
CRLF EQU 0A0Dh
EOF EQU 01Ah
ESCAPE EQU 01Bh
CAPMASK EQU 05Fh
;═══════════════════════════════════════════════════════════════════════════════
; === KEYS AND CODES ===
;═══════════════════════════════════════════════════════════════════════════════
;--- Key names in 8-byte field in ASCII order ---
; ASCII scan
; ~~~~~ ~~~~
KeyNames db '[!Down]',0 ; FFh B4h
db '[!End]',0,0 ; " B8h
db '[!Home]',0 ; " B7h
db '[!Left]',0 ; " B5h
db '[!PgDn]',0 ; " BAh
db '[!PgUp]',0 ; " B9h
db '[!Right]' ; " B6h
db '[!Tab]',0,0 ; " 8Fh
db '[!Up]',0,0,0 ; " B3h
db '[+]',0,0,0,0,0 ; " CEh
db '[-]',0,0,0,0,0 ; " CAh
db '[5]',0,0,0,0,0 ; " CCh
db '[Del]',0,0,0 ; " D3h
db '[Down]',0,0 ; " D0h
db '[End]',0,0,0 ; " CFh
EscKey db '[Esc]',0,0,0 ; (1Bh) Exception
db '[Home]',0,0 ; " C7h
db '[Ins]',0,0,0 ; " D2h
db '[Left]',0,0 ; " CBh
db '[PgDn]',0,0 ; " D1h
db '[PgUp]',0,0 ; " C9h
db '[Right]',0 ; " CDh
db '[Up]',0,0,0,0 ; " C8h
CtrlBkSp db '[^BkSp]',0 ; (7Fh) Exception
db '[^Down]',0 ; " C6h
db '[^End]',0,0 ; " F5h
CtrlEsc db '[^Esc]',0,0 ; " AAh
db '[^Home]',0 ; " F7h
db '[^Ins]',0,0 ; " C5h
db '[^Left]',0 ; " F3h
db '[^PgDn]',0 ; " F6h
db '[^PgUp]',0 ; " 84h
db '[^Right]' ; " F4h
db '[^Up]',0,0,0 ; " 8Dh
LASTKEYNAME EQU $ - 8
MINKEYLENGTH EQU 3 ; minimum length of key name, e.g. [+]
KEYNAMELENGTH EQU 8
KEYNAMENUMB EQU 34
;--- Scan codes for keys in above list, but ASCII codes for [Esc] and [^BkSp]
KeyCodes db 0B4h,0B8h,0B7h,0B5h,0BAh,0B9h,0B6h,08Fh,0B3h,0CEh
db 0CAh,0CCh,0D3h,0D0h,0CFh,01Bh,0C7h,0D2h,0CBh,0D1h
db 0C9h,0CDh,0C8h,07Fh,0C6h,0F5h,0AAh,0F7h,0C5h,0F3h
db 0F6h,084h,0F4h,08Dh
KEYCODENUMB EQU 34
;───────────────────────────────────────────────────────────────────────────────
;--- Scan codes for @A - @Z ---
AltXScan db 09Eh,0B0h,0AEh,0A0h,092h,0A1h,0A2h,0A3h,097h,0A4h
db 0A5h,0A6h,0B2h,0B1h,098h,099h,090h,093h,09Fh,094h
db 096h,0AFh,091h,0ADh,095h,0ACh
LASTALTXSCAN EQU $-1
LOWESTALTX EQU 090h ; lowest scan code in the list
HIGHESTALTX EQU 0B2h ; highest scan code in the list
ALTXNUMB EQU 26
;──────────────────────────────────────────────────────────────────────────────
CHARKEYLENGTH EQU 1
CharKeys db '0123456789'
Alphabet db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
LASTLETTER EQU $-1
CHARKEYLIMIT EQU $
;──────────────────────────────────────────────────────────────────────────────
FUNCKEYLENGTH EQU 4
FuncKeys db 'F1',0,0, 'F2',0,0, 'F3',0,0, 'F4',0,0, 'F5',0,0
db 'F6',0,0, 'F7',0,0, 'F8',0,0, 'F9',0,0, 'F10',0
db '!F1',0, '!F2',0, '!F3',0, '!F4',0, '!F5',0
db '!F6',0, '!F7',0, '!F8',0, '!F9',0, '!F10'
db '^F1',0, '^F2',0, '^F3',0, '^F4',0, '^F5',0
db '^F6',0, '^F7',0, '^F8',0, '^F9',0, '^F10'
db '@F1',0, '@F2',0, '@F3',0, '@F4',0, '@F5',0
db '@F6',0, '@F7',0, '@F8',0, '@F9',0, '@F10'
NRMFUNCLIMIT EQU $
db 'F11',0, 'F12',0, '!F11', '!F12'
db '^F11', '^F12', '@F11', '@F12'
EXTFUNCLIMIT EQU $
FUNCKEYNUMB EQU 48
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ MESSAGES ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Bmsg db ' bytes.',0
Fmsg db ' bytes of free space.',0
Cmsg db ' created. ',0
;──────────────────────────────────────────────────────────────────────────────
; ----- File Errors -----
XFcmsg db 'Cannot create the output file: ',0
XFfmsg db 'No files match this pattern: ',0
XFimsg db 'Wrong file identifier for V1.53+ or V1.70+ macros in ',0
XFkmsg db 'Labels are not allowed in .VTK files like ',0
XFlmsg db 'The 56kb buffer is not large enough for ',0
XFomsg db 'Cannot open this file: ',0
XFrmsg db 'Problem reading this file: ',0
XFvmsg db 'VDE Version 1.70+ does not use .VDK files like ',0
XFwmsg db 'Problem writing output data to ',0
XFxmsg db 'Wrong extension: ',0
;──────────────────────────────────────────────────────────────────────────────
; ----- Line Errors -----
XLamsg db ' An @ representing <Alt> is not followed by a letter of the alphabet.',CR,LF
db ' Use `@ for the @ character itself.',0
XLbmsg db ' In this line the definition exceeded the maximum length by ',0
XLcmsg db ' The last character should have ` in front of it or something after it.',0
XLdmsg db ' A caret (^) representing <Ctrl> is not followed by A-Z, [, \, ], ^, or _.',CR,LF
db ' Use `^ for the ^ character itself.',0
XLemsg db ' There is no equal sign.',0
XLlmsg db ' Bad label (too long, missing right bracket, etc.)',0
XLmmsg db ' Incorrect mode: (none), N, Q, B, [A for Version 1.70+ only]',0
XLnmsg db ' The key name is invalid, nonexistent, or not in the proper order.',0
XLsmsg db ' The maximum size of a macro file was exceeded in this line by ',0
XLxmsg db ' Autoexec has already been set for another function key.',0
XLymsg db ' The Autoexec setting can only be used in function key files.',0
;──────────────────────────────────────────────────────────────────────────────
BUFFERAREA EQU ($ + 1) AND 0FFFEh ; start buffers here since usage message
; is not needed during conversion
;──────────────────────────────────────────────────────────────────────────────
; ---- Usage Message ----
Umsg db CR,LF
db ' VMAC.COM (Version 1.11) Richard Cowell',CR,LF
db ' Compiler for VDE V1.53+ and V1.70+ Macros',CR,LF
db ' Converts: .VD[FK] macro files <--> .VT[FK] text files',CR,LF,CR,LF
db 'USAGE: VMAC {/U7} Filename {Fil*nam? ...}',CR,LF,CR,LF
db ' Options for converting macro files to text files:',CR,LF
db ' (none) = list ALL key names',CR,LF
db ' /U = list only names of keys USED for macros',CR,LF,CR,LF
db ' Option for converting .VTF text files to .VDF macro files:',CR,LF
db ' /7 = Version 1.70+ (maximum of 255 bytes/macro)',CR,LF,CR,LF
db 'Format of .VT[FK] text file:',CR,LF
db '[Key] {< Label >} Mode = Definition (Mode: none, Q, N, B, {A for V1.70+})',CR,LF
db ' {= Continuation} (Label: only for V.1.70+)',CR,LF,CR,LF
db 'Special character (`):',CR,LF
db ' Use `@ `^ `` for the literal characters @ ^ `',CR,LF
db ' Use ` in front of a space: 1) at the beginning of a definition',CR,LF
db ' 2) at the end of a definition with a comment',CR,LF,0
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ HEAP ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
CAPKEYNAMES EQU BUFFERAREA
LASTCAPNAME EQU CAPKEYNAMES + ( (KEYNAMENUMB - 1) * KEYNAMELENGTH )
CAPKEYSIZE EQU KEYNAMENUMB * KEYNAMELENGTH
DTA EQU CAPKEYNAMES + CAPKEYSIZE
DTANAME EQU DTA + 30
DTASIZE EQU 48 ; 43 + 5 byte margin
PATH EQU DTA + DTASIZE
PATHSIZE EQU 64
SYMBUFFER EQU PATH + PATHSIZE
SYMSIZE EQU 16
MACBUFFER EQU SYMBUFFER + SYMSIZE
MACFLAG EQU MACBUFFER + 1
MACSTART1 EQU MACBUFFER + 2 ; start of def w/o label, or label
MACSTART2 EQU MACBUFFER + 9 ; start of def with label
DEFLENGTH5 EQU 126 ; bytes allowed in V1.53 macro def.
DEFLENGTH7 EQU 253 ; bytes allowed in V1.70 macro def.
MACLIMIT5 EQU MACBUFFER + DEFLENGTH5 + 2 ; 2 = length + mode bytes
MACLIMIT7 EQU MACBUFFER + DEFLENGTH7 + 2
MACBUFFSIZE EQU 512 ; provide a little margin
VDXBUFFER EQU MACBUFFER + MACBUFFSIZE
VDXMACLIMIT EQU 974 ; bytes available for mode+def
VDXFILELIMIT EQU VDXBUFFER + 1024 ; .VD[FK] files are 1024 bytes
VDXSIZE EQU 1024 + 256 ; provide a little margin
TEXTBUFFER EQU VDXBUFFER + VDXSIZE
HEAPEND EQU 0FFFEh
STACKSIZE EQU 1024
TEXTSIZE EQU HEAPEND - STACKSIZE - TEXTBUFFER ; about 57,000 bytes
;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒