3 ;--------------------------------------------------------------------;
6 ; V1.1 8/23/82 M.A.Ulloa ;
8 ; V1.2 9/22/82 M.A.Ulloa ;
9 ; Added the -c and -n options ;
12 ; Added DOS version number control ;
14 ; 10/07/82 Rev.2 M.A.Ulloa ;
15 ; Changed quote for double quotes, and added ;
16 ; file name printing ;
18 ; 10/20/82 Rev.3 M.A.Ulloa ;
19 ; Modified IBM name to FIND, and changed the text ;
22 ; 10/25/82 Rev.4 M.A.Ulloa ;
23 ; Changed name to FIND and all messages to the ;
26 ; 10/27/82 Rev.5 M.A.Ulloa ;
27 ; Made the correct exit on version check in case ;
30 ; 11/4/82 Rev. 5 A.R. Reynolds ;
31 ; Messages moved to external module ;
33 ; 11/10/82 Rev. 6 M.A. Ulloa ;
34 ; Corrected problem with line numbers, and a problem ;
35 ; with seeking for 0 chars. ;
37 ; 03/30/83 Rev. 7 M.A. Ulloa ;
38 ; Added patch area for bug fixing. ;
40 ; 04/14/83 Rev. 8 M.A. Ulloa ;
41 ; Made changes for Kanji characters. (uhg!) ;
43 ;--------------------------------------------------------------------;
48 KANJI equ FALSE
;set to true is kanji vers.
50 ;--------------------------------------------------------------------;
51 ; FIND program following the standart UNIX operation. ;
54 ; find {option} string {filename {filename} {...}} ;
57 ; 1) String arguments HAVE to be enclosed ;
58 ; in double quotes. (Two double quotes if a ;
59 ; doble quote is to be included). Only ONE ;
60 ; string argument is presently allowed. ;
62 ; 2) Options are available: ;
63 ; v All lines but those matching are considered ;
64 ; c Only print a count of matching lines ;
65 ; n Each line is preceded by its relative ;
66 ; line number in the file. ;
68 ; - Options can be Upper or lower case. ;
69 ; - Format: The switch character followed by an options ;
70 ; character. I.e.: In the IBM PC: /v ;
72 ; 3) The program returns: ;
73 ; 0 - OK, and some matches ;
76 ; 4) The maximum line size is determined by ;
77 ; buffer size. Bigger lines will bomb the program. ;
79 ; 5) If no file name is given then it will asssume ;
80 ; the input is comming from the Standart Input. NO ;
81 ; errors are reported when reading from Standart Input. ;
82 ;--------------------------------------------------------------------;
85 assume
cs:code,ss:code,ds:nothing
,es:nothing
88 CR equ
0dh ;A Carriage Return
89 LF equ
0ah ;A Line Feed
90 quote_char equ 22h
;A double quote character
93 buffer_size equ
4096 ;file buffer size
94 st_buf_size equ
128 ;string arg. buffer size
95 fname_buf_size equ
64 ;file name buffer size
98 ;----- DOS EQUATES --------------------------------------------------;
99 std_in equ
0 ;STD input handle
100 std_out equ
1 ;STD output handle
101 std_err equ
2 ;STD error handle
102 dos_ent equ 21h
;DOS entry point
104 std_con_string_output equ
9
106 char_oper equ
55 ;get configuration parameters
107 open equ
61 ;DOS std open code
108 close equ
62 ;DOS std close code
109 read equ
63 ;DOS std read code
110 write equ
64 ;DOS std write code
111 lseek equ
66 ;DOS file seek
112 exit equ
76 ;DOS process exit code
115 ;----- Misc Data -----------------------------------------------;
116 make db "***MAUlloa/Microsoft/V12***"
122 n2_buf db 8 dup(0) ;buffer for number conversion
126 ;----- OPTION FLAGS -------------------------------------------------;
127 ; If a flag is set (0ffh) then the option has been selected, if
128 ;reset (0) then it has been not. All options are reset initially.
129 ; NOTE: the order of this table has to remain consistent with the
130 ;options dispatch code. If any changes are made they have to
131 ;correspond with the code.
142 ;----- LINE COUNTERS ------------------------------------------------;
143 mtch_cntr dw 0 ;matched lines counter
144 line_cntr dw 0 ;line counter
147 ;----- MAIN ROUTINE -------------------------------------------------;
150 ;----- CHECK VERSION NUMBER -----------------------------------------;
158 mov dx,offset bad_vers
159 mov ah,std_con_string_output
161 push es ;bad vers, exit a la 1.x
165 badfart proc
far ;(what a hack!!)
171 push cs ;load ES to the right area,
172 pop es ; for use with DI register
176 ;--------------------------------------------------------------------;
178 mov si,81h
;Start addrss. of commad line buf.
180 call kill_bl
;Get rid of blanks
181 or bx,bx ;A CR found?
182 jz find_opt
;no, first find the options
184 mov dx,offset errmsg1
;empty command line, no args: error.
187 mov al,2 ;error code for exit
191 ;----- FIND THE OPTION IF ANY ---------------------------------------;
193 mov ah,char_oper
;get the dos switch char.
195 int dos_ent
;switch char in DL
198 lodsb ;get the first char of command line
201 cmp al,CR
;a Carriage Return
203 pop dx ;get switch character
204 cmp al,dl ;is it the switch char?
205 jne find_str
;no, no options: get the string
206 push dx ;save for another round
208 lodsb ;get the option character
210 je cont_scan
;yes, ignore and continue
212 je args_missing
;yes, error...
213 call make_caps
;Capitalize the character
214 mov bx,offset opt_tbl
;pointer to option flag table
216 cmp al,'V' ;the v option?
218 cmp al,'C' ;the c option?
220 cmp al,'N' ;the n option?
223 mov cs:errmsg5_opt
,al ;save the option
224 mov dx,offset errmsg5
;unknown option: error
227 mov dx,offset crlf
;print a CRLF
230 jmp another_opt
;process next option
234 jmp short opt_dispatch
238 jmp short opt_dispatch
244 mov es:byte ptr[bx+di],0ffh ;set the corresponding flag
245 jmp another_opt
;process the rest of the options
249 call kill_bl
;get rid of blanks
250 or bx,bx ;A CR found?
251 jz another_opt
;no, test for other options
252 jmp args_missing
;yes, error...
255 ;----- FIND STRING ARGUMENT -----------------------------------------;
257 cmp al,quote_char
;string should start with a
258 jnz bad_str_err
; quote character, if not: error.
259 mov di,offset st_buffer
;String argument buffer addrss.
260 xor cx,cx ;Clear to keep string length.
264 cmp al,CR
;if a CR is found in the string
265 jnz str_ok
; then it's a bad string
267 mov dx,offset errmsg2
;bad string error message
269 call prt_err
;print the error.
274 cmp al,quote_char
;look for a quote character
275 jnz move_char
;not an apost., move to buffer
276 lodsb ;an apost., check next char.
277 cmp al,quote_char
;another quote character?
278 je move_char
;yes, move it to the buffer
279 dec si ;no, adjust the pointer
280 mov es:st_length
,cx ;store the string length
281 or cx,cx ;Is the string empty?
282 jnz other_args
;no: get the rest of the args.
283 mov al,1 ;empty: no matches(!?)
287 inc cx ;increment string length
291 ;----- FIND THE FILE ARGUMENTS --------------------------------------;
292 other_args: ;Process the rest of the command
294 call kill_bl
;get rid of leading blanks
295 or bx,bx ;At least one argument necessary,
296 jz further_args
; if a CR not found: ok.
298 ;----- USE STD IN FOR INPUT -----------------------------------------;
301 mov ax,std_in
;handle
305 call clr_cntrs
;set all counters to zero
306 mov di,offset file_name_buf
;Set pointer to the name buffer
307 xor cx,cx ;zero file name length
310 cmp al,' ' ;A blank: end of file name,
312 cmp al,CR
;A CR: idem.
314 stosb ;store in name buffer
315 inc cx ;increment file name length
318 dec si ;Adjust pointer for next round.
319 mov es:byte ptr[di],00h ;File names are null terminated
320 push si ;Save SI to continue com. line scan.
321 push ds ;Save DS register contents for
322 ; later because it points to the
323 ; rest of the arguments.
324 mov es:file_name_len
,cx ;save the name length
326 ;----- OPEN FILE FOR READING ----------------------------------------;
327 push cs ;Load new DS with CS
329 mov dx,offset file_name_buf
;addrss. of the file name
331 mov al,0 ;file open for reading
332 int dos_ent
;call the DOS
333 jnc say_name
;if no carry then no errors
336 ;----- PRINT FILE NAME ----------------------------------------------;
338 push ax ;save file handle
339 mov dx,offset heading
340 mov cl,cs:heading_len
344 mov dx,offset file_name_buf
345 mov cx,ds:file_name_len
348 cmp ds:c_flg
,0ffh ;count only flag set?
358 ;----- Fill Buffer for Matching -------------------------------------;
360 mov bx,ax ;retrieve handle
362 mov dx,offset buffer
;data buffer addrss.
366 jnc no_read_error
;if carry then read error
369 or ax,ax ;if ax=0 then all done
371 cmp ds:c_flg
,0ffh ;count only flag set?
375 cmp bx,std_in
;Using STD IN?
377 jmp foo
;if so: all done, exit
379 mov ah,close
;otherwise close the file
381 jmp scan_rest
;get another file
383 ;----- MATCH ROUTINE ------------------------------------------------;
384 ;Note: If input is being taken from a file the stack contains
385 ; (from top to bottom):
386 ; - Pointer to the next command in the command line
387 ; - Pointer to the program segment prefix (to be loaded into
388 ; DS to access the command line.
389 ; if the imput is from the standart input then NONE of it will be
393 push bx ;save the file handle
394 mov bp,offset buffer
;ptr to first line of file
395 mov di,ax ;dispalcement from beg of buffer
397 cmp ax,buffer_size
-1 ;last line of the file?
398 jg no_last_line
;if yes, add a CRLF just in case
400 cmp byte ptr[bx+di-1],LF
;finished with a LF?
401 je no_last_line
;yes, it's an OK line.
402 mov byte ptr[bx+di],CR
;put a CR at the end of the data
404 mov byte ptr[bx+di],LF
;put a LF ...
408 push di ;save the # of chars. in the buffer
410 mov dx,ds:st_length
;length of the string arg.
411 dec dx ;adjust for later use
420 ;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------;
421 ;Note: at this point the stack contains (from top to bottom):
422 ; - Stuff mentioned before
424 ; - Number of chars. left in the buffer from the next line.
425 ; - Addrs. of the next line in the buffer.
427 ; plus, DX has the adjusted length of the string argument.
430 inc ds:line_cntr
;increment line counter
431 pop bp ;addrs. of next line in the buffer
432 mov di,bp ;points to beg. of a line
433 pop cx ;get # of chars left in the buffer
434 mov bx,cx ;save in case a non-complete line
435 mov al,LF
;search for a Line Feed
436 jcxz more_stuff_o
;no chars left in buffer
438 jnz more_stuff_o
;no full line left in buffer
440 push cx ;save chars left in buffer
441 push di ;points to beg. of next line
443 sub cx,bp ;length of the current line
444 mov bx,cx ;save in case it has a match
446 dec cx ;CRLF characters discounted
447 jcxz try_again_opt
;if line empty go to next line
448 mov di,bp ;pointer to the beg. of current line
453 ; CX adjusted line length
454 ; DX adjusted string argument length
455 ; DI points to beg. of line
460 push dx ;save for next line
464 inc dx ;different algorithm!
465 mov si,offset st_buffer
;pointer to beg. of string argument
470 call is_prefix
;check for a prefix char
474 cmp cx,1 ; Can not compare a two byte char
475 jz try_again_opt1
; if there is only one available
478 call next_kchar
;no match, advance di to next kanji
479 jc try_again_opt1
;not enough chars left in line
480 jmp short lop
;try another char in line
486 call next_kchar
;no match, advance di to next kanji
487 jc try_again_opt1
;not enough chars left in line
488 jmp short lop
;try another char in line
496 dec dx ;last char had prefix so it was
500 jz a_matchk
; no chars left: a match!
503 jmp comp_next_char
; loop if chars left in arg.
510 mov si,offset st_buffer
;pointer to beg. of string argument
511 lodsb ;get first character of the str. arg.
512 repnz scasb ;search for a match in current line
513 jnz try_again_opt
;no match, try the next line
514 cmp cx,dx ;compare lengths, a full match is not
515 jb try_again_opt
; possible if CX < DX.
516 push di ;save addrs. of next char. in the line
517 push cx ;save the # of chars. left in the line
518 mov cx,dx ;get the adjusted string arg. length
519 jcxz a_match
;if a single char string, then match!
520 repz cmpsb ;compare string with line
521 jz a_match
;a match found, hurrah!
522 pop cx ;no match, get # of chars remaining
524 pop di ;position of the next char. in the line
528 ;----- A MATCH: CHECK FOR THE v OPTION ------------------------------;
534 cmp ds:v_flg
,0ffh ;is flag set?
535 jne prt_line
;no, print the line
538 ;----- NO MATCH: CHECK FOR THE v OPTION -----------------------------;
540 cmp ds:v_flg
,0ffh ;is flag set?
541 jne try_again
;no goto next line
543 ;----- PRINT THE LINE WITH THE MATCH --------------------------------;
544 ;Note: at this point the stack contains (top to bottom)
545 ; - Stuff mentioned before
547 ; plus, BP points to begginig of the current line, BX has the length
548 ;of the current line including the CRLF, and DX the adjusted length of
549 ;the string argument.
552 cmp ds:c_flg
,0ffh ;is count only flag set?
554 inc ds:mtch_cntr
;yes, increment counter
558 push dx ;save the adjusted string arg. length
559 cmp ds:n_flg
,0ffh ;is line number flag set?
569 ;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------;
570 ; The scanning routines have detected that the buffer does not
571 ;contain a full line any more. More lines have to be read into the
572 ;buffer. But first perform a seek on the file in order to re-read
573 ;the non-complete line into the begining of the buffer.
574 ; Uppon entry BP contains points to the begining of the non-complete
575 ;line, and BX has the number of characters left in the buffer.
576 ; The Stack contains (top to bottom):
577 ; - Pointer to the next command in the command line
578 ; - Pointer to the program segment prefix (to be loaded into
579 ; DS to access the command line).
583 mov dx,bx ;get chars left in buffer
584 pop bx ;get the handle
585 or dx,dx ;are there 0 left?
586 jz no_seek
;yes, do not seek
587 neg dx ;form two's complement
589 mov al,1 ;seek from the current position
590 mov ah,lseek
;seek on file
594 jmp refill
;no errors: refill the buffer
596 cmp bx,std_in
;Using STD IN?
597 je foo
;if so: all done, exit
598 mov ah,close
;close the file
600 mov dx,offset errmsg4_pre
;read error
601 mov cl,cs:errlen4_pre
602 call prt_file_name
;print the file name in error
603 mov dx,offset errmsg4_post
;read error
604 mov cl,cs:errlen4_post
607 ;----- PRINT ERRORS -------------------------------------------------;
609 mov dx,offset errmsg3_pre
;error in open operation
610 mov cl,cs:errlen3_pre
611 call prt_err_2
;print error message
612 call prt_file_name
;print the file name in error
613 mov dx,offset errmsg3_post
;error in open operation
614 mov cl,cs:errlen3_post
616 call prt_err_2
;print error message
618 ;----- SCAN THE REST OF THE COMMAND LINE ----------------------------;
620 pop ds ;restore pointer to comm. line
621 pop si ;restore pointer to next comm.
622 call kill_bl
;look for further args.
623 or bx,bx ;test for a CR
627 mov al,0 ;Proper code
629 mov ah,exit
;All done, exit with proper code.
633 ;--------------------------------------------------------------------;
634 ; Get rid of blanks in command line. ;
635 ; Advances the SI reg till the next non-blank character, if the ;
636 ; character is a CR (0dh) then returns with BX non-zero, otherwise ;
640 ; SI points to the first character on the line to scan. ;
643 ; SI points to the first non-blank character found. ;
644 ; BX contains 0D hex if the first non-blank found is ;
645 ; a Carriage Return, otherwise it is 0. ;
650 ;--------------------------------------------------------------------;
653 xor bx,bx ;zero bx to start: no CR found
655 lodsb ;get rid of blanks
660 mov bx,ax ;make bx non-zero (actually 0dh)
662 dec si ;adjust pointer
666 ;--------------------------------------------------------------------;
668 ;--------------------------------------------------------------------;
670 mov byte ptr es:mtch_cntr
,0
671 mov byte ptr es:line_cntr
,0
674 ;--------------------------------------------------------------------;
675 ; Print Count of Matched lines ;
677 ; Modifies: AX,CX,DX and DI ;
678 ;--------------------------------------------------------------------;
681 cmp bx,std_in
;using std_in?
682 jz sj3
;if so do not print file name
686 call prout
;print colon
689 mov di,offset n2_buf
;buffer for characters
690 call bin2asc
;convert to ascii
692 call prout
;print the number
695 call prout
;print an end of line
700 ;--------------------------------------------------------------------;
701 ; Print relative line number ;
703 ; Modifies: AX,CX and DI ;
704 ;--------------------------------------------------------------------;
720 ;--------------------------------------------------------------------;
721 ; Print string to STD_OUT ;
722 ;--------------------------------------------------------------------;
730 ;--------------------------------------------------------------------;
731 ; Binary to Ascii conversion routine ;
735 ; DI Points to one past the last char in the ;
739 ; Result in the buffer MSD first ;
743 ; AX,BX,CX,DX and DI ;
745 ;--------------------------------------------------------------------;
755 add dl,'0' ;convert to ASCII
771 ;--------------------------------------------------------------------;
772 ; Print the current file name ;
775 ; DX, CX, BX and AX ;
776 ;--------------------------------------------------------------------;
778 mov dx,offset file_name_buf
;print the file name
779 mov cx,ds:file_name_len
;retrive file name length
783 ;--------------------------------------------------------------------;
784 ; Print an error message to the Standart error ;
787 ; DX has the pointer to the message ;
788 ; CX has the length of the message ;
792 ;--------------------------------------------------------------------;
794 push ds ;Save the current DS
795 push cs ;Make DS point to the right
796 pop ds ; place, for DOS use.
805 int dos_ent
;write error message
809 ;--------------------------------------------------------------------;
810 ; CAPIALIZES THE CHARACTER IN AL ;
813 ; AL has the character to Capitalize ;
816 ; AL has the capitalized character ;
820 ;--------------------------------------------------------------------;
834 ;--------------------------------------------------------------------;
835 ; ADVANCE POINTER TO NEXT KANJI CHARACTER ;
837 ; entry: DI points to a Kanji string ;
838 ; CX length in bytes of the string ;
840 ; exit: DI points to next Kanji char ;
841 ; CX has number of bytes left ;
845 ;--------------------------------------------------------------------;
852 jcxz no_kleft
; for insurance
864 ;--------------------------------------------------------------------;
865 ; FIND OUT IS THE BYTE IS A KANJI PREFIX ;
867 ; entry: DI points to a kanji string ;
869 ; exit: Carry set if it is a kanji prefix ;
873 ;--------------------------------------------------------------------;
894 ;----- PATCH AREA ---------------------------------------------------;
896 patch_area dw 100h
dup(?
)
900 ;----- BUFFER AREA --------------------------------------------------;
901 st_length dw 0 ;String argumnet length
902 st_buffer db st_buf_size
dup(?
) ;String argument buffer
904 file_name_len dw 0 ;File name length
905 file_name_buf db fname_buf_size
+1 dup(?
) ;File name buffer,(allow for
908 buffer db buffer_size
+1 dup(?
) ;file buffer, the last byte is
909 ;a guard in case of forced insertion
912 ;----- ERROR MESSAGES -----------------------------------------------;
913 EXTRN bad_vers
:byte,crlf
:byte,errmsg1
:byte,errlen1
:byte,errmsg2
:byte
914 EXTRN errmsg3_pre
:byte,errlen3_pre
:byte
915 EXTRN errmsg3_post
:byte,errlen3_post
:byte
916 EXTRN errmsg4_pre
:byte,errlen4_pre
:byte
917 EXTRN errmsg4_post
:byte,errlen4_post
:byte
918 EXTRN heading
:byte,heading_len
:byte,errlen2
:byte
919 EXTRN errmsg5
:byte,errmsg5_opt
:byte,errlen5
:byte
923 ;----- STACK AREA ---------------------------------------------------;