mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-25 23:25: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
|
||
|