📄 cmdedit.asm
字号:
;
; CMDEDIT.ASM
;(c) 1989, 1990 PC Magazine and Ashok P. Nadkarni
;
SIGNATURE1 equ <"CMDEDIT 2.0 (c) 1990 Ziff Communications Co.">
SIGNATURE2 equ <"PC Magazine">
SIGNATURE3 equ <"Ashok P. Nadkarni">
; Main module for command line editor.
INCLUDE common.inc
INCLUDE general.inc
INCLUDE ascii.inc
INCLUDE buffers.inc
INCLUDE dos.inc
INCLUDE bios.inc
PUBLIC dos_version_major
PUBLIC dos_version_minor
PUBLIC resident
PUBLIC macro_level
PUBLIC cur_macro
PUBLIC cur_macro_len
PUBLIC linebuf
PUBLIC linelimit
PUBLIC dot
PUBLIC lastchar
PUBLIC LINEBUF_END
PUBLIC edit_mode
PUBLIC default_imode
PUBLIC caller_cursor
PUBLIC omode_cursor
PUBLIC pgm_name
PUBLIC macrosize
PUBLIC symsize
PUBLIC dossize
PUBLIC dirsize
PUBLIC mfilename
PUBLIC mfile_seen
PUBLIC macro_ignore_char
PUBLIC cmdlen
PUBLIC silent
PUBLIC endm_cmd
PUBLIC defs
PUBLIC defm
PUBLIC tsr_install_end
PUBLIC source
PUBLIC abort_processing
PUBLIC disp_line
PUBLIC set_disp_marks
PUBLIC insert_at_dot
PUBLIC insert_chars
PUBLIC remove_chars
PUBLIC erase_to_dot
PUBLIC init_over
PUBLIC line_to_scr
PUBLIC get_next_line
PUBLIC reset_line
PUBLIC in_appl
PUBLIC user_command
PUBLIC our_break_handler
PUBLIC prev_isr1b
PUBLIC old_int21vec
PUBLIC cmdedit_isr
PUBLIC makeroom
PUBLIC locate_dosenv
PUBLIC cmdedit
IFE TSR
PUBLIC cmdedit_cmd
PUBLIC debug_loop
PUBLIC freadline
PUBLIC get_file_line
PUBLIC read_cmdfile
PUBLIC disp_prompt
PUBLIC prompt
PUBLIC init_screen
ENDIF
DGROUP GROUP CSEG
CSEG SEGMENT PARA PUBLIC 'CODE'
EXTRN install_begin:BYTE
EXTRN install:PROC
EXTRN execute_defs:PROC
EXTRN execute_defm:PROC
EXTRN execute_dels:PROC
EXTRN execute_delm:PROC
EXTRN execute_cmdstat:PROC
EXTRN execute_pushd:PROC
EXTRN execute_popd:PROC
EXTRN execute_chd:PROC
EXTRN hist_init:PROC
EXTRN hist_type:PROC
EXTRN hist_top:PROC
EXTRN dirs_init:PROC
EXTRN macro_init:PROC
EXTRN symbol_init:PROC
EXTRN expand_macro:PROC
EXTRN expand_symbol:PROC
EXTRN get_macro_line:PROC
EXTRN skip_whitespace:PROC
EXTRN skip_nonwhite:PROC
EXTRN stre_cmp:PROC
EXTRN get_kbd_line:PROC
EXTRN getargs:PROC
EXTRN file_error:BYTE
EXTRN abort_install:PROC
EXTRN expand_var:PROC
EXTRN execute_rsthist:PROC
EXTRN execute_rstmac:PROC
EXTRN execute_rstsym:PROC
EXTRN execute_rstdir:PROC
; Define important fields in the PSP.
ASSUME CS:DGROUP
ORG 2Ch
env dw ? ;Segment of environment block
ORG 80h
PROMPT_BUF_SIZE EQU 80
prompt LABEL BYTE ;buffer used for prompt after TSRing
cmdlen DB ? ;Offset 80h in the PSP contains length of command
; line when program is invoked
ORG 80h+PROMPT_BUF_SIZE
prompt_length dw ?
cur_macro LABEL BYTE ;Start of area used after TSRing to
; store the current macro expansion.
ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
ORG 100h
entry: jmp install
; The following variables are LOST after TSRing since the space is
; reused for other purposes.
mfilename db 64 DUP (0) ;Storage for ASCIIZ filename
mfile_seen db 0 ;Indicate if command line
; specified an init file
mfile_handle dw ? ;Handle for open file
; Entry init_over is jumped to from the installation code after all the
; command line parsing has been done. This part of the installation
; remains resident. It is not kept with the install code because that
; code sections gets overwritten with various buffers.
init_over proc near
; The command parameters have been parsed. Now get ready to terminate.
mov si,offset DGROUP:install_begin
;First location in installation code
mov bx,si ; is where the buffers start.
mov ax,dossize ;Size of DOS history buffer
add si,ax ;SI <- end of DOS buffer
xor cx,cx ;Indicate DOS mode
call near ptr hist_init ;Initialize DOS history buffer
mov bx,si ;Repeat for directory stack
mov ax,dirsize
add si,ax
call near ptr dirs_init
mov bx,si ;And finally for the macros
mov ax,macrosize
add si,ax
call near ptr macro_init
mov bx,si ;And finally for the macros
mov ax,symsize
add si,ax
call near ptr symbol_init
; SI->end of buffer area
; Read in the command file
call near ptr init_screen ;Need to do this because
; reset_line (called by
; execute_defm) restores cursor shape.
call near ptr read_cmdfile
; Initialize var source to get the next line from the keyboard.
mov source,offset DGROUP:get_kbd_line
; All data structures initalized. Now setup stack pointer, release
; unneeded memory back to DOS, set up interrupt handler and TSR.
push es ;save ES
mov es,env ;Don't need environment block
ASSUME ES:NOTHING
mov ah,49h
int 21h ;Release the block
IF TSR
mov ax,3521h ;Get old interrupt vector
int 21h
mov old_int21vec,bx ;Remember offset
mov old_int21vec+2,es ;Remember segment
mov dx,offset DGROUP:cmdedit_isr ;Our handler
;DS = CS already
mov ax,2521h ;Set intr vector
int 21h
ENDIF
pop es ;Restore ES
ASSUME ES:DGROUP
lea dx,STACK_SIZE+15[si] ;Calculate end of TSR portion
; DX<-num bytes to keep resident
and dl,0f0h ; rounded to para
; Note DX->BEYOND last byte of program
mov new_sp,dx ;Remember it
mov resident,1 ;Indicate we're TSR
IFE TSR
; Don't actually TSR
debug_loop:
@init_over_10:
@DispCh CR
@DispCh LF
lea dx,dummy_prompt
@DispStr dx
mov dx,offset DGROUP:debug_buf ;Offset
mov debug_buf,DEBUG_BUFSIZE-2
mov ah,0Ah ;Function code
pushf ;Simulate interrupt
push cs ;Simulate interrupt
call near ptr cmdedit_isr ;Simulate interrupt
jmp short @init_over_10 ;Keep looping
debug_buf db 256 DUP (?)
DEBUG_BUFSIZE equ $-debug_buf
dummy_prompt db "dummy>",DOLLAR
ENDIF
int 27h ;TSR
init_over endp
;+
; FUNCTION : read_cmdfile
;
; Reads commands from a file. The filename is in the variable
; mfilename. The space occupied this function is overwritten
; after TSRing so it must NOT be called once the program is resident.
;
; Parameters:
; None.
;
; Returns:
; AX = 0 on success, any other value if failure
;
; Register(s) destroyed:
; AX,BX,CX,DX
;-
read_cmdfile proc near
@save si,di
cmp mfile_seen,0
je @read_cmdfile_100 ;No file specified
@OpenFil mfilename,0
jc @read_cmdfile_92 ;CF=1 for errors
@read_cmdfile_30:
mov source,offset DGROUP:get_file_line
; We want get_next_line to read
; from the file.
mov mfile_handle,ax ;Save file handle
@read_cmdfile_50:
mov dx,offset DGROUP:linebuf ;Destination for file line
mov ax,LINEBUF_SIZE
call near ptr freadline ;Get next line into buffer
;AX contains line length
jnc @read_cmdfile_80 ;no error or EOF
or ax,ax ;No more bytes ?
jz @read_cmdfile_99 ;EOF is not error
jmp short @read_cmdfile_90 ;Error, abort install
@read_cmdfile_80:
mov dx,offset DGROUP:linebuf
add dx,ax
mov lastchar,dx ;Update end of line
call near ptr cmdedit_cmd ;Execute as a command
jnc @read_cmdfile_50 ;If not a command, better be a
; blank line
call near ptr blankline
jnc @read_cmdfile_50 ;Ignore blank lines
; If not blank line and not CMDEDIT command, then error error handler
@read_cmdfile_90:
; Come here for error
@ClosFil mfile_handle ;Close the file
@read_cmdfile_92:
@DispStr file_error
mov ax,-1 ;Indicate exit code
jmp abort_install ;Exit program
@read_cmdfile_99:
@ClosFil mfile_handle ;Close the file
jc @read_cmdfile_92 ;Abort if error closnig file
@read_cmdfile_100:
@restore
ret
read_cmdfile endp
;+
; FUNCTION : get_file_line
;
; Called indirectly through the global variable 'source'.
; Currently this routine exists only during installation and must
; NOT be called once the program is a TSR. The next line from the
; file is copied to linebuf. If there is no next line, the
; installation is aborted.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
; Register(s) destroyed:
; AX,BX,CX,DX
;-
get_file_line proc near
mov dx,offset DGROUP:linebuf
mov ax,LINEBUF_SIZE
call near ptr freadline
jnc @get_file_line_99
;Error reading file or EOF
@DispStr file_error
jmp abort_install
@get_file_line_99:
mov dx,offset DGROUP:linebuf
add dx,ax
mov lastchar,dx ;Update end of line
ret
get_file_line endp
;+
; FUNCTION : freadline
;
; Reads a line at a time from the file whose handle is in
; mfile_handle into the buffer pointed to by AX. If the buffer is
; too small or if there are any errors, the routine returns with CF set.
; If EOF, then AX = 0 and CF is set.
;
; Parameters:
; DX = address of buffer
; AX = size of buffer
;
; Returns:
; CF = 0 if no errors (and not EOF), else 1.
; AX = num chars in line if CF = 0.
; 0 if EOF, ffff for other errors if CF = 1
;
; Register(s) destroyed:
;-
freadline proc near
@save si,di
mov di,dx ;DI->buffer
mov bx,mfile_handle
mov si,ax ;SI<-num bytes to read
xchg cx,ax ;CX<-num bytes to read
mov ah,3Fh ;File read function
int 21h
jc @freadline_99 ;Error!
mov cx,ax ;CX<-num bytes read
jcxz @freadline_99_a ;EOF (note AX is 0 indicating EOF)
xchg dx,ax ;DX<-num bytes read
mov bx,di ;BX->start of buffer
mov al,CR
repne scasb ;Hunt for CR
je @freadline_50 ;Found
; No CR found, this better be the last line in file.
cmp dx,si ;Were fewer bytes read than requested?
cmc
jc @freadline_99 ;Error
push dx ;Save length of line
xor ax,ax ;AX<-num extra bytes read
jmp short @freadline_60
@freadline_50:
stc ;Assume line too long
jcxz @freadline_99 ;error if match in last char
; (line too long)
cmp BYTE PTR [di],LF ;Next char must be linefeed
stc ;Assume error
jne @freadline_99 ;Indeed an error if not LF
mov ax,di
sub ax,bx ;AX<-num chars including CR
sub dx,ax
xchg ax,dx
dec dx ;DX<-num chars in line
dec ax ;AX<-num extra chars read
push dx ;Save num chars in line
@freadline_60:
; Top of stack contains num bytes in line.
; Now position file pointer to 'unread' characters.
; AX contains the num of extra characters read.
neg ax
cwd
mov cx,ax
xchg cx,dx ;CX:DX<-num bytes to 'unread'
mov bx,mfile_handle
mov ax,4201h ;Move file ptr relative
int 21h ;Seek file relative
; CF set/reset by error status
pop ax ;AX<-num bytes in line
clc ;No errors
jmp short @freadline_100
@freadline_99:
mov ax,0ffffh ;Non-EOF error
@freadline_99_a:
stc ;Indicate error or EOF
@freadline_100:
@restore
ret
freadline endp
;+
; FUNCTION : blankline
;
; Checks whether the line in linebuf is blank or not. Also treats it
; as blank line if it begins with a `-'.
;
; Parameters:
; None.
;
; Returns:
; CF = 0 if blank line, else 1.
; Register(s) destroyed:
; AX,BX,CX,DX
;-
blankline proc near
@save si
mov si,offset DGROUP:linebuf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -