mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 17:15:47 +00:00
932 lines
38 KiB
NASM
932 lines
38 KiB
NASM
|
title MSDOS V2.0 FIND
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Revision History: ;
|
|||
|
; ;
|
|||
|
; V1.1 8/23/82 M.A.Ulloa ;
|
|||
|
; ;
|
|||
|
; V1.2 9/22/82 M.A.Ulloa ;
|
|||
|
; Added the -c and -n options ;
|
|||
|
; ;
|
|||
|
; 9/23/82 M.A.Ulloa ;
|
|||
|
; Added DOS version number control ;
|
|||
|
; ;
|
|||
|
; 10/07/82 Rev.2 M.A.Ulloa ;
|
|||
|
; Changed quote for double quotes, and added ;
|
|||
|
; file name printing ;
|
|||
|
; ;
|
|||
|
; 10/20/82 Rev.3 M.A.Ulloa ;
|
|||
|
; Modified IBM name to FIND, and changed the text ;
|
|||
|
; of some messages. ;
|
|||
|
; ;
|
|||
|
; 10/25/82 Rev.4 M.A.Ulloa ;
|
|||
|
; Changed name to FIND and all messages to the ;
|
|||
|
; IBM form. ;
|
|||
|
; ;
|
|||
|
; 10/27/82 Rev.5 M.A.Ulloa ;
|
|||
|
; Made the correct exit on version check in case ;
|
|||
|
; of a 1.x DOS. ;
|
|||
|
; ;
|
|||
|
; 11/4/82 Rev. 5 A.R. Reynolds ;
|
|||
|
; Messages moved to external module ;
|
|||
|
; ;
|
|||
|
; 11/10/82 Rev. 6 M.A. Ulloa ;
|
|||
|
; Corrected problem with line numbers, and a problem ;
|
|||
|
; with seeking for 0 chars. ;
|
|||
|
; ;
|
|||
|
; 03/30/83 Rev. 7 M.A. Ulloa ;
|
|||
|
; Added patch area for bug fixing. ;
|
|||
|
; ;
|
|||
|
; 04/14/83 Rev. 8 M.A. Ulloa ;
|
|||
|
; Made changes for Kanji characters. (uhg!) ;
|
|||
|
; ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
|
|||
|
FALSE equ 0
|
|||
|
TRUE equ NOT FALSE
|
|||
|
|
|||
|
KANJI equ FALSE ;set to true is kanji vers.
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; FIND program following the standart UNIX operation. ;
|
|||
|
; ;
|
|||
|
; FORMAT: ;
|
|||
|
; find {option} string {filename {filename} {...}} ;
|
|||
|
; ;
|
|||
|
; NOTES: ;
|
|||
|
; 1) String arguments HAVE to be enclosed ;
|
|||
|
; in double quotes. (Two double quotes if a ;
|
|||
|
; doble quote is to be included). Only ONE ;
|
|||
|
; string argument is presently allowed. ;
|
|||
|
; ;
|
|||
|
; 2) Options are available: ;
|
|||
|
; v All lines but those matching are considered ;
|
|||
|
; c Only print a count of matching lines ;
|
|||
|
; n Each line is preceded by its relative ;
|
|||
|
; line number in the file. ;
|
|||
|
; ;
|
|||
|
; - Options can be Upper or lower case. ;
|
|||
|
; - Format: The switch character followed by an options ;
|
|||
|
; character. I.e.: In the IBM PC: /v ;
|
|||
|
; ;
|
|||
|
; 3) The program returns: ;
|
|||
|
; 0 - OK, and some matches ;
|
|||
|
; 2 - Some Error ;
|
|||
|
; ;
|
|||
|
; 4) The maximum line size is determined by ;
|
|||
|
; buffer size. Bigger lines will bomb the program. ;
|
|||
|
; ;
|
|||
|
; 5) If no file name is given then it will asssume ;
|
|||
|
; the input is comming from the Standart Input. NO ;
|
|||
|
; errors are reported when reading from Standart Input. ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
|
|||
|
code segment public
|
|||
|
assume cs:code,ss:code,ds:nothing,es:nothing
|
|||
|
|
|||
|
|
|||
|
CR equ 0dh ;A Carriage Return
|
|||
|
LF equ 0ah ;A Line Feed
|
|||
|
quote_char equ 22h ;A double quote character
|
|||
|
|
|||
|
|
|||
|
buffer_size equ 4096 ;file buffer size
|
|||
|
st_buf_size equ 128 ;string arg. buffer size
|
|||
|
fname_buf_size equ 64 ;file name buffer size
|
|||
|
|
|||
|
|
|||
|
;----- DOS EQUATES --------------------------------------------------;
|
|||
|
std_in equ 0 ;STD input handle
|
|||
|
std_out equ 1 ;STD output handle
|
|||
|
std_err equ 2 ;STD error handle
|
|||
|
dos_ent equ 21h ;DOS entry point
|
|||
|
|
|||
|
std_con_string_output equ 9
|
|||
|
get_version equ 48
|
|||
|
char_oper equ 55 ;get configuration parameters
|
|||
|
open equ 61 ;DOS std open code
|
|||
|
close equ 62 ;DOS std close code
|
|||
|
read equ 63 ;DOS std read code
|
|||
|
write equ 64 ;DOS std write code
|
|||
|
lseek equ 66 ;DOS file seek
|
|||
|
exit equ 76 ;DOS process exit code
|
|||
|
|
|||
|
|
|||
|
;----- Misc Data -----------------------------------------------;
|
|||
|
make db "***MAUlloa/Microsoft/V12***"
|
|||
|
rev db "8"
|
|||
|
|
|||
|
|
|||
|
colon db ": "
|
|||
|
n1_buf db "["
|
|||
|
n2_buf db 8 dup(0) ;buffer for number conversion
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;----- OPTION FLAGS -------------------------------------------------;
|
|||
|
; If a flag is set (0ffh) then the option has been selected, if
|
|||
|
;reset (0) then it has been not. All options are reset initially.
|
|||
|
; NOTE: the order of this table has to remain consistent with the
|
|||
|
;options dispatch code. If any changes are made they have to
|
|||
|
;correspond with the code.
|
|||
|
|
|||
|
opt_tbl:
|
|||
|
|
|||
|
v_flg db 0
|
|||
|
c_flg db 0
|
|||
|
n_flg db 0
|
|||
|
x_flg db 0 ;not used
|
|||
|
l_flg db 0 ;not used
|
|||
|
|
|||
|
|
|||
|
;----- LINE COUNTERS ------------------------------------------------;
|
|||
|
mtch_cntr dw 0 ;matched lines counter
|
|||
|
line_cntr dw 0 ;line counter
|
|||
|
|
|||
|
|
|||
|
;----- MAIN ROUTINE -------------------------------------------------;
|
|||
|
start:
|
|||
|
|
|||
|
;----- CHECK VERSION NUMBER -----------------------------------------;
|
|||
|
|
|||
|
mov ah,get_version
|
|||
|
int 21h
|
|||
|
cmp al,2
|
|||
|
jge vers_ok
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov dx,offset bad_vers
|
|||
|
mov ah,std_con_string_output
|
|||
|
int 21h
|
|||
|
push es ;bad vers, exit a la 1.x
|
|||
|
xor ax,ax
|
|||
|
push ax
|
|||
|
|
|||
|
badfart proc far ;(what a hack!!)
|
|||
|
ret
|
|||
|
badfart endp
|
|||
|
|
|||
|
vers_ok:
|
|||
|
|
|||
|
push cs ;load ES to the right area,
|
|||
|
pop es ; for use with DI register
|
|||
|
|
|||
|
assume es:code
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
|
|||
|
mov si,81h ;Start addrss. of commad line buf.
|
|||
|
|
|||
|
call kill_bl ;Get rid of blanks
|
|||
|
or bx,bx ;A CR found?
|
|||
|
jz find_opt ;no, first find the options
|
|||
|
args_missing:
|
|||
|
mov dx,offset errmsg1 ;empty command line, no args: error.
|
|||
|
mov cl,cs:errlen1
|
|||
|
call prt_err
|
|||
|
mov al,2 ;error code for exit
|
|||
|
jmp done
|
|||
|
|
|||
|
|
|||
|
;----- FIND THE OPTION IF ANY ---------------------------------------;
|
|||
|
find_opt:
|
|||
|
mov ah,char_oper ;get the dos switch char.
|
|||
|
mov al,0
|
|||
|
int dos_ent ;switch char in DL
|
|||
|
push dx
|
|||
|
another_opt:
|
|||
|
lodsb ;get the first char of command line
|
|||
|
cmp al,' ' ;a blank?
|
|||
|
je cont_scan
|
|||
|
cmp al,CR ;a Carriage Return
|
|||
|
je args_missing
|
|||
|
pop dx ;get switch character
|
|||
|
cmp al,dl ;is it the switch char?
|
|||
|
jne find_str ;no, no options: get the string
|
|||
|
push dx ;save for another round
|
|||
|
|
|||
|
lodsb ;get the option character
|
|||
|
cmp al,' ' ;a blank?
|
|||
|
je cont_scan ;yes, ignore and continue
|
|||
|
cmp al,CR ;a CR?
|
|||
|
je args_missing ;yes, error...
|
|||
|
call make_caps ;Capitalize the character
|
|||
|
mov bx,offset opt_tbl ;pointer to option flag table
|
|||
|
|
|||
|
cmp al,'V' ;the v option?
|
|||
|
je opt_v
|
|||
|
cmp al,'C' ;the c option?
|
|||
|
je opt_c
|
|||
|
cmp al,'N' ;the n option?
|
|||
|
je opt_n
|
|||
|
|
|||
|
mov cs:errmsg5_opt,al ;save the option
|
|||
|
mov dx,offset errmsg5 ;unknown option: error
|
|||
|
mov cl,cs:errlen5
|
|||
|
call prt_err
|
|||
|
mov dx,offset crlf ;print a CRLF
|
|||
|
mov cx,2
|
|||
|
call prt_err
|
|||
|
jmp another_opt ;process next option
|
|||
|
|
|||
|
opt_v:
|
|||
|
mov di,0
|
|||
|
jmp short opt_dispatch
|
|||
|
|
|||
|
opt_c:
|
|||
|
mov di,1
|
|||
|
jmp short opt_dispatch
|
|||
|
|
|||
|
opt_n:
|
|||
|
mov di,2
|
|||
|
|
|||
|
opt_dispatch:
|
|||
|
mov es:byte ptr[bx+di],0ffh ;set the corresponding flag
|
|||
|
jmp another_opt ;process the rest of the options
|
|||
|
|
|||
|
cont_scan:
|
|||
|
dec si ;adjust SI
|
|||
|
call kill_bl ;get rid of blanks
|
|||
|
or bx,bx ;A CR found?
|
|||
|
jz another_opt ;no, test for other options
|
|||
|
jmp args_missing ;yes, error...
|
|||
|
|
|||
|
|
|||
|
;----- FIND STRING ARGUMENT -----------------------------------------;
|
|||
|
find_str:
|
|||
|
cmp al,quote_char ;string should start with a
|
|||
|
jnz bad_str_err ; quote character, if not: error.
|
|||
|
mov di,offset st_buffer ;String argument buffer addrss.
|
|||
|
xor cx,cx ;Clear to keep string length.
|
|||
|
|
|||
|
move_str:
|
|||
|
lodsb
|
|||
|
cmp al,CR ;if a CR is found in the string
|
|||
|
jnz str_ok ; then it's a bad string
|
|||
|
bad_str_err:
|
|||
|
mov dx,offset errmsg2 ;bad string error message
|
|||
|
mov cl,cs:errlen2
|
|||
|
call prt_err ;print the error.
|
|||
|
mov al,2
|
|||
|
jmp done
|
|||
|
|
|||
|
str_ok:
|
|||
|
cmp al,quote_char ;look for a quote character
|
|||
|
jnz move_char ;not an apost., move to buffer
|
|||
|
lodsb ;an apost., check next char.
|
|||
|
cmp al,quote_char ;another quote character?
|
|||
|
je move_char ;yes, move it to the buffer
|
|||
|
dec si ;no, adjust the pointer
|
|||
|
mov es:st_length,cx ;store the string length
|
|||
|
or cx,cx ;Is the string empty?
|
|||
|
jnz other_args ;no: get the rest of the args.
|
|||
|
mov al,1 ;empty: no matches(!?)
|
|||
|
jmp done
|
|||
|
move_char:
|
|||
|
stosb ;put in buffer
|
|||
|
inc cx ;increment string length
|
|||
|
jmp move_str
|
|||
|
|
|||
|
|
|||
|
;----- FIND THE FILE ARGUMENTS --------------------------------------;
|
|||
|
other_args: ;Process the rest of the command
|
|||
|
; line arguments.
|
|||
|
call kill_bl ;get rid of leading blanks
|
|||
|
or bx,bx ;At least one argument necessary,
|
|||
|
jz further_args ; if a CR not found: ok.
|
|||
|
|
|||
|
;----- USE STD IN FOR INPUT -----------------------------------------;
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ax,std_in ;handle
|
|||
|
jmp fill
|
|||
|
|
|||
|
further_args:
|
|||
|
call clr_cntrs ;set all counters to zero
|
|||
|
mov di,offset file_name_buf ;Set pointer to the name buffer
|
|||
|
xor cx,cx ;zero file name length
|
|||
|
move_fname:
|
|||
|
lodsb
|
|||
|
cmp al,' ' ;A blank: end of file name,
|
|||
|
je done_move
|
|||
|
cmp al,CR ;A CR: idem.
|
|||
|
je done_move
|
|||
|
stosb ;store in name buffer
|
|||
|
inc cx ;increment file name length
|
|||
|
jmp move_fname
|
|||
|
done_move:
|
|||
|
dec si ;Adjust pointer for next round.
|
|||
|
mov es:byte ptr[di],00h ;File names are null terminated
|
|||
|
push si ;Save SI to continue com. line scan.
|
|||
|
push ds ;Save DS register contents for
|
|||
|
; later because it points to the
|
|||
|
; rest of the arguments.
|
|||
|
mov es:file_name_len,cx ;save the name length
|
|||
|
|
|||
|
;----- OPEN FILE FOR READING ----------------------------------------;
|
|||
|
push cs ;Load new DS with CS
|
|||
|
pop ds
|
|||
|
mov dx,offset file_name_buf ;addrss. of the file name
|
|||
|
mov ah,open
|
|||
|
mov al,0 ;file open for reading
|
|||
|
int dos_ent ;call the DOS
|
|||
|
jnc say_name ;if no carry then no errors
|
|||
|
jmp open_error
|
|||
|
|
|||
|
;----- PRINT FILE NAME ----------------------------------------------;
|
|||
|
say_name:
|
|||
|
push ax ;save file handle
|
|||
|
mov dx,offset heading
|
|||
|
mov cl,cs:heading_len
|
|||
|
xor ch,ch
|
|||
|
call prout
|
|||
|
|
|||
|
mov dx,offset file_name_buf
|
|||
|
mov cx,ds:file_name_len
|
|||
|
call prout
|
|||
|
|
|||
|
cmp ds:c_flg,0ffh ;count only flag set?
|
|||
|
je xx1
|
|||
|
|
|||
|
mov dx,offset crlf
|
|||
|
mov cx,2
|
|||
|
call prout
|
|||
|
|
|||
|
xx1:
|
|||
|
pop ax
|
|||
|
|
|||
|
;----- Fill Buffer for Matching -------------------------------------;
|
|||
|
fill:
|
|||
|
mov bx,ax ;retrieve handle
|
|||
|
refill:
|
|||
|
mov dx,offset buffer ;data buffer addrss.
|
|||
|
mov cx,buffer_size
|
|||
|
mov ah,read
|
|||
|
int dos_ent
|
|||
|
jnc no_read_error ;if carry then read error
|
|||
|
jmp read_error
|
|||
|
no_read_error:
|
|||
|
or ax,ax ;if ax=0 then all done
|
|||
|
jnz go_match
|
|||
|
cmp ds:c_flg,0ffh ;count only flag set?
|
|||
|
jne sj2
|
|||
|
call print_count
|
|||
|
sj2:
|
|||
|
cmp bx,std_in ;Using STD IN?
|
|||
|
jnz regular
|
|||
|
jmp foo ;if so: all done, exit
|
|||
|
regular:
|
|||
|
mov ah,close ;otherwise close the file
|
|||
|
int dos_ent
|
|||
|
jmp scan_rest ;get another file
|
|||
|
|
|||
|
;----- MATCH ROUTINE ------------------------------------------------;
|
|||
|
;Note: If input is being taken from a file the stack contains
|
|||
|
; (from top to bottom):
|
|||
|
; - Pointer to the next command in the command line
|
|||
|
; - Pointer to the program segment prefix (to be loaded into
|
|||
|
; DS to access the command line.
|
|||
|
; if the imput is from the standart input then NONE of it will be
|
|||
|
; in the stack.
|
|||
|
|
|||
|
go_match:
|
|||
|
push bx ;save the file handle
|
|||
|
mov bp,offset buffer ;ptr to first line of file
|
|||
|
mov di,ax ;dispalcement from beg of buffer
|
|||
|
|
|||
|
cmp ax,buffer_size-1 ;last line of the file?
|
|||
|
jg no_last_line ;if yes, add a CRLF just in case
|
|||
|
mov bx,bp
|
|||
|
cmp byte ptr[bx+di-1],LF ;finished with a LF?
|
|||
|
je no_last_line ;yes, it's an OK line.
|
|||
|
mov byte ptr[bx+di],CR ;put a CR at the end of the data
|
|||
|
inc di
|
|||
|
mov byte ptr[bx+di],LF ;put a LF ...
|
|||
|
inc di
|
|||
|
|
|||
|
no_last_line:
|
|||
|
push di ;save the # of chars. in the buffer
|
|||
|
push bp
|
|||
|
mov dx,ds:st_length ;length of the string arg.
|
|||
|
dec dx ;adjust for later use
|
|||
|
jmp short try_again
|
|||
|
|
|||
|
|
|||
|
more_stuff_o:
|
|||
|
jmp more_stuff
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------;
|
|||
|
;Note: at this point the stack contains (from top to bottom):
|
|||
|
; - Stuff mentioned before
|
|||
|
; - File Handle
|
|||
|
; - Number of chars. left in the buffer from the next line.
|
|||
|
; - Addrs. of the next line in the buffer.
|
|||
|
;
|
|||
|
; plus, DX has the adjusted length of the string argument.
|
|||
|
|
|||
|
try_again:
|
|||
|
inc ds:line_cntr ;increment line counter
|
|||
|
pop bp ;addrs. of next line in the buffer
|
|||
|
mov di,bp ;points to beg. of a line
|
|||
|
pop cx ;get # of chars left in the buffer
|
|||
|
mov bx,cx ;save in case a non-complete line
|
|||
|
mov al,LF ;search for a Line Feed
|
|||
|
jcxz more_stuff_o ;no chars left in buffer
|
|||
|
repnz scasb
|
|||
|
jnz more_stuff_o ;no full line left in buffer
|
|||
|
|
|||
|
push cx ;save chars left in buffer
|
|||
|
push di ;points to beg. of next line
|
|||
|
mov cx,di
|
|||
|
sub cx,bp ;length of the current line
|
|||
|
mov bx,cx ;save in case it has a match
|
|||
|
dec cx
|
|||
|
dec cx ;CRLF characters discounted
|
|||
|
jcxz try_again_opt ;if line empty go to next line
|
|||
|
mov di,bp ;pointer to the beg. of current line
|
|||
|
another_char:
|
|||
|
;
|
|||
|
; On entry:
|
|||
|
; BX line length
|
|||
|
; CX adjusted line length
|
|||
|
; DX adjusted string argument length
|
|||
|
; DI points to beg. of line
|
|||
|
;
|
|||
|
|
|||
|
IF KANJI
|
|||
|
|
|||
|
push dx ;save for next line
|
|||
|
lop:
|
|||
|
pop dx
|
|||
|
push dx
|
|||
|
inc dx ;different algorithm!
|
|||
|
mov si,offset st_buffer ;pointer to beg. of string argument
|
|||
|
|
|||
|
comp_next_char:
|
|||
|
push di
|
|||
|
mov di,si
|
|||
|
call is_prefix ;check for a prefix char
|
|||
|
pop di
|
|||
|
jnc nopre
|
|||
|
lodsw
|
|||
|
cmp cx,1 ; Can not compare a two byte char
|
|||
|
jz try_again_opt1 ; if there is only one available
|
|||
|
cmp ax,word ptr [di]
|
|||
|
jz kmatch1
|
|||
|
call next_kchar ;no match, advance di to next kanji
|
|||
|
jc try_again_opt1 ;not enough chars left in line
|
|||
|
jmp short lop ;try another char in line
|
|||
|
|
|||
|
nopre:
|
|||
|
lodsb
|
|||
|
cmp al,byte ptr [di]
|
|||
|
jz kmatch
|
|||
|
call next_kchar ;no match, advance di to next kanji
|
|||
|
jc try_again_opt1 ;not enough chars left in line
|
|||
|
jmp short lop ;try another char in line
|
|||
|
|
|||
|
try_again_opt1:
|
|||
|
pop dx
|
|||
|
jmp try_again_opt
|
|||
|
|
|||
|
|
|||
|
kmatch1:
|
|||
|
dec dx ;last char had prefix so it was
|
|||
|
; long.
|
|||
|
kmatch:
|
|||
|
dec dx
|
|||
|
jz a_matchk ; no chars left: a match!
|
|||
|
call next_kchar
|
|||
|
jc try_again_opt1
|
|||
|
jmp comp_next_char ; loop if chars left in arg.
|
|||
|
|
|||
|
a_matchk:
|
|||
|
pop dx
|
|||
|
|
|||
|
ELSE
|
|||
|
|
|||
|
mov si,offset st_buffer ;pointer to beg. of string argument
|
|||
|
lodsb ;get first character of the str. arg.
|
|||
|
repnz scasb ;search for a match in current line
|
|||
|
jnz try_again_opt ;no match, try the next line
|
|||
|
cmp cx,dx ;compare lengths, a full match is not
|
|||
|
jb try_again_opt ; possible if CX < DX.
|
|||
|
push di ;save addrs. of next char. in the line
|
|||
|
push cx ;save the # of chars. left in the line
|
|||
|
mov cx,dx ;get the adjusted string arg. length
|
|||
|
jcxz a_match ;if a single char string, then match!
|
|||
|
repz cmpsb ;compare string with line
|
|||
|
jz a_match ;a match found, hurrah!
|
|||
|
pop cx ;no match, get # of chars remaining
|
|||
|
; in the line.
|
|||
|
pop di ;position of the next char. in the line
|
|||
|
jmp another_char
|
|||
|
|
|||
|
|
|||
|
;----- A MATCH: CHECK FOR THE v OPTION ------------------------------;
|
|||
|
a_match:
|
|||
|
pop ax ;adjust stack
|
|||
|
pop ax
|
|||
|
ENDIF
|
|||
|
|
|||
|
cmp ds:v_flg,0ffh ;is flag set?
|
|||
|
jne prt_line ;no, print the line
|
|||
|
jmp try_again
|
|||
|
|
|||
|
;----- NO MATCH: CHECK FOR THE v OPTION -----------------------------;
|
|||
|
try_again_opt:
|
|||
|
cmp ds:v_flg,0ffh ;is flag set?
|
|||
|
jne try_again ;no goto next line
|
|||
|
|
|||
|
;----- PRINT THE LINE WITH THE MATCH --------------------------------;
|
|||
|
;Note: at this point the stack contains (top to bottom)
|
|||
|
; - Stuff mentioned before
|
|||
|
;
|
|||
|
; plus, BP points to begginig of the current line, BX has the length
|
|||
|
;of the current line including the CRLF, and DX the adjusted length of
|
|||
|
;the string argument.
|
|||
|
|
|||
|
prt_line:
|
|||
|
cmp ds:c_flg,0ffh ;is count only flag set?
|
|||
|
jne no_c_flg
|
|||
|
inc ds:mtch_cntr ;yes, increment counter
|
|||
|
jmp try_again
|
|||
|
|
|||
|
no_c_flg:
|
|||
|
push dx ;save the adjusted string arg. length
|
|||
|
cmp ds:n_flg,0ffh ;is line number flag set?
|
|||
|
jne no_n_flg
|
|||
|
call prt_lcntr
|
|||
|
no_n_flg:
|
|||
|
mov dx,bp
|
|||
|
mov cx,bx
|
|||
|
call prout
|
|||
|
pop dx ;restore
|
|||
|
jmp try_again
|
|||
|
|
|||
|
;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------;
|
|||
|
; The scanning routines have detected that the buffer does not
|
|||
|
;contain a full line any more. More lines have to be read into the
|
|||
|
;buffer. But first perform a seek on the file in order to re-read
|
|||
|
;the non-complete line into the begining of the buffer.
|
|||
|
; Uppon entry BP contains points to the begining of the non-complete
|
|||
|
;line, and BX has the number of characters left in the buffer.
|
|||
|
; The Stack contains (top to bottom):
|
|||
|
; - Pointer to the next command in the command line
|
|||
|
; - Pointer to the program segment prefix (to be loaded into
|
|||
|
; DS to access the command line).
|
|||
|
; - File handle.
|
|||
|
|
|||
|
more_stuff:
|
|||
|
mov dx,bx ;get chars left in buffer
|
|||
|
pop bx ;get the handle
|
|||
|
or dx,dx ;are there 0 left?
|
|||
|
jz no_seek ;yes, do not seek
|
|||
|
neg dx ;form two's complement
|
|||
|
mov cx,-1
|
|||
|
mov al,1 ;seek from the current position
|
|||
|
mov ah,lseek ;seek on file
|
|||
|
int dos_ent
|
|||
|
jc read_error
|
|||
|
no_seek:
|
|||
|
jmp refill ;no errors: refill the buffer
|
|||
|
read_error:
|
|||
|
cmp bx,std_in ;Using STD IN?
|
|||
|
je foo ;if so: all done, exit
|
|||
|
mov ah,close ;close the file
|
|||
|
int dos_ent
|
|||
|
mov dx,offset errmsg4_pre ;read error
|
|||
|
mov cl,cs:errlen4_pre
|
|||
|
call prt_file_name ;print the file name in error
|
|||
|
mov dx,offset errmsg4_post ;read error
|
|||
|
mov cl,cs:errlen4_post
|
|||
|
jmp r_error
|
|||
|
|
|||
|
;----- PRINT ERRORS -------------------------------------------------;
|
|||
|
open_error:
|
|||
|
mov dx,offset errmsg3_pre ;error in open operation
|
|||
|
mov cl,cs:errlen3_pre
|
|||
|
call prt_err_2 ;print error message
|
|||
|
call prt_file_name ;print the file name in error
|
|||
|
mov dx,offset errmsg3_post ;error in open operation
|
|||
|
mov cl,cs:errlen3_post
|
|||
|
r_error:
|
|||
|
call prt_err_2 ;print error message
|
|||
|
|
|||
|
;----- SCAN THE REST OF THE COMMAND LINE ----------------------------;
|
|||
|
scan_rest:
|
|||
|
pop ds ;restore pointer to comm. line
|
|||
|
pop si ;restore pointer to next comm.
|
|||
|
call kill_bl ;look for further args.
|
|||
|
or bx,bx ;test for a CR
|
|||
|
jnz foo
|
|||
|
jmp further_args
|
|||
|
foo:
|
|||
|
mov al,0 ;Proper code
|
|||
|
done:
|
|||
|
mov ah,exit ;All done, exit with proper code.
|
|||
|
int dos_ent
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Get rid of blanks in command line. ;
|
|||
|
; Advances the SI reg till the next non-blank character, if the ;
|
|||
|
; character is a CR (0dh) then returns with BX non-zero, otherwise ;
|
|||
|
; BX is zero. ;
|
|||
|
; ;
|
|||
|
; entry: ;
|
|||
|
; SI points to the first character on the line to scan. ;
|
|||
|
; ;
|
|||
|
; exit: ;
|
|||
|
; SI points to the first non-blank character found. ;
|
|||
|
; BX contains 0D hex if the first non-blank found is ;
|
|||
|
; a Carriage Return, otherwise it is 0. ;
|
|||
|
; ;
|
|||
|
; modifies: ;
|
|||
|
; BX, SI, and AX ;
|
|||
|
; ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
kill_bl:
|
|||
|
cld ;increment
|
|||
|
xor bx,bx ;zero bx to start: no CR found
|
|||
|
no_bl:
|
|||
|
lodsb ;get rid of blanks
|
|||
|
cmp al,' '
|
|||
|
je no_bl
|
|||
|
cmp al,CR
|
|||
|
jnz no_cr
|
|||
|
mov bx,ax ;make bx non-zero (actually 0dh)
|
|||
|
no_cr:
|
|||
|
dec si ;adjust pointer
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Clear Counters ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
clr_cntrs:
|
|||
|
mov byte ptr es:mtch_cntr,0
|
|||
|
mov byte ptr es:line_cntr,0
|
|||
|
ret
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Print Count of Matched lines ;
|
|||
|
; ;
|
|||
|
; Modifies: AX,CX,DX and DI ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
print_count:
|
|||
|
push bx ;save handle
|
|||
|
cmp bx,std_in ;using std_in?
|
|||
|
jz sj3 ;if so do not print file name
|
|||
|
|
|||
|
mov dx,offset colon
|
|||
|
mov cx,2
|
|||
|
call prout ;print colon
|
|||
|
sj3:
|
|||
|
mov ax,ds:mtch_cntr
|
|||
|
mov di,offset n2_buf ;buffer for characters
|
|||
|
call bin2asc ;convert to ascii
|
|||
|
mov dx,offset n2_buf
|
|||
|
call prout ;print the number
|
|||
|
mov dx,offset crlf
|
|||
|
mov cx,2
|
|||
|
call prout ;print an end of line
|
|||
|
pop bx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Print relative line number ;
|
|||
|
; ;
|
|||
|
; Modifies: AX,CX and DI ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
prt_lcntr:
|
|||
|
push bx
|
|||
|
push dx
|
|||
|
mov ax,ds:line_cntr
|
|||
|
mov di,offset n2_buf
|
|||
|
call bin2asc
|
|||
|
mov byte ptr[di],"]"
|
|||
|
inc cx
|
|||
|
inc cx
|
|||
|
mov dx,offset n1_buf
|
|||
|
call prout
|
|||
|
pop dx
|
|||
|
pop bx
|
|||
|
ret
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Print string to STD_OUT ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
prout:
|
|||
|
mov bx,std_out
|
|||
|
mov ah,write
|
|||
|
int dos_ent
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Binary to Ascii conversion routine ;
|
|||
|
; ;
|
|||
|
; Entry: ;
|
|||
|
; AX Binary number ;
|
|||
|
; DI Points to one past the last char in the ;
|
|||
|
; result buffer. ;
|
|||
|
; ;
|
|||
|
; Exit: ;
|
|||
|
; Result in the buffer MSD first ;
|
|||
|
; CX Digit count ;
|
|||
|
; ;
|
|||
|
; Modifies: ;
|
|||
|
; AX,BX,CX,DX and DI ;
|
|||
|
; ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
bin2asc:
|
|||
|
mov bx,0ah
|
|||
|
xor cx,cx
|
|||
|
go_div:
|
|||
|
inc cx
|
|||
|
cmp ax,bx
|
|||
|
jb div_done
|
|||
|
xor dx,dx
|
|||
|
div bx
|
|||
|
add dl,'0' ;convert to ASCII
|
|||
|
push dx
|
|||
|
jmp short go_div
|
|||
|
|
|||
|
div_done:
|
|||
|
add al,'0'
|
|||
|
push ax
|
|||
|
mov bx,cx
|
|||
|
deposit:
|
|||
|
pop ax
|
|||
|
stosb
|
|||
|
loop deposit
|
|||
|
mov cx,bx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Print the current file name ;
|
|||
|
; ;
|
|||
|
; modifies: ;
|
|||
|
; DX, CX, BX and AX ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
prt_file_name:
|
|||
|
mov dx,offset file_name_buf ;print the file name
|
|||
|
mov cx,ds:file_name_len ;retrive file name length
|
|||
|
jmp short prt_err_2
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; Print an error message to the Standart error ;
|
|||
|
; ;
|
|||
|
; entry: ;
|
|||
|
; DX has the pointer to the message ;
|
|||
|
; CX has the length of the message ;
|
|||
|
; ;
|
|||
|
; modifies: ;
|
|||
|
; BX and AX ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
prt_err:
|
|||
|
push ds ;Save the current DS
|
|||
|
push cs ;Make DS point to the right
|
|||
|
pop ds ; place, for DOS use.
|
|||
|
call prt_err_2
|
|||
|
pop ds
|
|||
|
ret
|
|||
|
|
|||
|
prt_err_2:
|
|||
|
xor ch,ch
|
|||
|
mov bx,std_err
|
|||
|
mov ah,write
|
|||
|
int dos_ent ;write error message
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; CAPIALIZES THE CHARACTER IN AL ;
|
|||
|
; ;
|
|||
|
; entry: ;
|
|||
|
; AL has the character to Capitalize ;
|
|||
|
; ;
|
|||
|
; exit: ;
|
|||
|
; AL has the capitalized character ;
|
|||
|
; ;
|
|||
|
; modifies: ;
|
|||
|
; AL ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
make_caps:
|
|||
|
cmp al,'a'
|
|||
|
jb no_cap
|
|||
|
cmp al,'z'
|
|||
|
jg no_cap
|
|||
|
and al,0dfh
|
|||
|
no_cap:
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
IF KANJI
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; ADVANCE POINTER TO NEXT KANJI CHARACTER ;
|
|||
|
; ;
|
|||
|
; entry: DI points to a Kanji string ;
|
|||
|
; CX length in bytes of the string ;
|
|||
|
; ;
|
|||
|
; exit: DI points to next Kanji char ;
|
|||
|
; CX has number of bytes left ;
|
|||
|
; ;
|
|||
|
; modifies: AX ;
|
|||
|
; ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
next_kchar:
|
|||
|
jcxz no_kleft
|
|||
|
call is_prefix
|
|||
|
jnc no_p
|
|||
|
inc di
|
|||
|
dec cx
|
|||
|
jcxz no_kleft ; for insurance
|
|||
|
no_p:
|
|||
|
inc di
|
|||
|
dec cx
|
|||
|
clc
|
|||
|
ret
|
|||
|
|
|||
|
no_kleft:
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
; FIND OUT IS THE BYTE IS A KANJI PREFIX ;
|
|||
|
; ;
|
|||
|
; entry: DI points to a kanji string ;
|
|||
|
; ;
|
|||
|
; exit: Carry set if it is a kanji prefix ;
|
|||
|
; ;
|
|||
|
; modifies: AX ;
|
|||
|
; ;
|
|||
|
;--------------------------------------------------------------------;
|
|||
|
is_prefix:
|
|||
|
mov al,byte ptr [di]
|
|||
|
cmp al,81h
|
|||
|
jb nok
|
|||
|
cmp al,0a0h
|
|||
|
jb isk
|
|||
|
cmp al,0e0h
|
|||
|
jb nok
|
|||
|
cmp al,0fdh
|
|||
|
jb isk
|
|||
|
nok:
|
|||
|
clc
|
|||
|
ret
|
|||
|
isk:
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
;----- PATCH AREA ---------------------------------------------------;
|
|||
|
|
|||
|
patch_area dw 100h dup(?)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
;----- BUFFER AREA --------------------------------------------------;
|
|||
|
st_length dw 0 ;String argumnet length
|
|||
|
st_buffer db st_buf_size dup(?) ;String argument buffer
|
|||
|
|
|||
|
file_name_len dw 0 ;File name length
|
|||
|
file_name_buf db fname_buf_size+1 dup(?) ;File name buffer,(allow for
|
|||
|
; null at the end).
|
|||
|
|
|||
|
buffer db buffer_size+1 dup(?) ;file buffer, the last byte is
|
|||
|
;a guard in case of forced insertion
|
|||
|
;of a CRLF pair.
|
|||
|
|
|||
|
;----- ERROR MESSAGES -----------------------------------------------;
|
|||
|
EXTRN bad_vers:byte,crlf:byte,errmsg1:byte,errlen1:byte,errmsg2:byte
|
|||
|
EXTRN errmsg3_pre:byte,errlen3_pre:byte
|
|||
|
EXTRN errmsg3_post:byte,errlen3_post:byte
|
|||
|
EXTRN errmsg4_pre:byte,errlen4_pre:byte
|
|||
|
EXTRN errmsg4_post:byte,errlen4_post:byte
|
|||
|
EXTRN heading:byte,heading_len:byte,errlen2:byte
|
|||
|
EXTRN errmsg5:byte,errmsg5_opt:byte,errlen5:byte
|
|||
|
code ends
|
|||
|
|
|||
|
|
|||
|
;----- STACK AREA ---------------------------------------------------;
|
|||
|
stack segment stack
|
|||
|
|
|||
|
dw 64 dup(?,?)
|
|||
|
stack_top equ $
|
|||
|
|
|||
|
stack ends
|
|||
|
|
|||
|
end start
|
|||
|
|