summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FIND
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/FIND')
-rw-r--r--v4.0/src/CMD/FIND/FIND.ASM1664
-rw-r--r--v4.0/src/CMD/FIND/FIND.INC100
-rw-r--r--v4.0/src/CMD/FIND/FIND.LNK4
-rw-r--r--v4.0/src/CMD/FIND/FIND.SKL12
-rw-r--r--v4.0/src/CMD/FIND/FINDMES.ASM19
-rw-r--r--v4.0/src/CMD/FIND/MAKEFILE34
6 files changed, 1833 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FIND/FIND.ASM b/v4.0/src/CMD/FIND/FIND.ASM
new file mode 100644
index 0000000..459765a
--- /dev/null
+++ b/v4.0/src/CMD/FIND/FIND.ASM
@@ -0,0 +1,1664 @@
1 title DOS FIND Utility
2; 0
3;********************************************************************
4;*
5;* UTILITY NAME: find.exe
6;*
7;* SOURCE FILE NAME: find.asm
8;*
9;* STATUS: Find utility, DOS Version 4.0
10;*
11;* SYNTAX (Command line)
12;*
13;* FIND [/V][/C][/N] "string" [[d:][path]filename[.ext]...]
14;*
15;* where:
16;*
17;* /V - Display all lines NOT containing the string
18;* /C - Display only a count of lines containing string
19;* /N - Display number of line containing string
20;*
21;*
22;* UTILITY FUNCTION:
23;*
24;* Searches the specified file(s) looking for the string the user
25;* entered from the command line. If file name(s) are specifeied,
26;* those names are displayed, and if the string is found, then the
27;* entire line containing that string will be displayed. Optional
28;* parameters modify that behavior and are described above. String
29;* arguments have to be enclosed in double quotes. (Two double quotes
30;* if a double quote is to be included). Only one string argument is
31;* presently allowed. The maximum line size is determined by buffer
32;* size. Bigger lines will bomb the program. If no file name is given
33;* then it will asssume the input is coming from the standard Input.
34;* No errors are reported when reading from standard Input.
35;*
36;*
37;* EXIT:
38;* The program returns errorlevel:
39;* 0 - OK, and some matches
40;* 1 -
41;* 2 - Some Error
42;*
43;*
44;* Revision History:
45;*
46;* V1.1 8/23/82 M.A.U. (Microsoft)
47;*
48;* V1.2 9/22/82 M.A.U. (Microsoft)
49;* Added the -c and -n options
50;*
51;* 9/23/82 M.A.U. (Microsoft)
52;* Added DOS version number control
53;*
54;* 10/07/82 Rev.2 M.A.U. (Microsoft)
55;* Changed quote for double quotes, and added
56;* file name printing
57;*
58;* 10/20/82 Rev.3 M.A.U. (Microsoft)
59;* Modified IBM name to FIND, and changed the text
60;* of some messages.
61;*
62;* 10/25/82 Rev.4 M.A.U. (Microsoft)
63;* Changed name to FIND and all messages to the
64;* IBM form.
65;*
66;* 10/27/82 Rev.5 M.A.U. (Microsoft)
67;* Made the correct exit on version check in case
68;* of a 1.x DOS.
69;*
70;* 11/4/82 Rev. 5 A.R. Reynolds (Microsoft)
71;* Messages moved to external module
72;*
73;* 11/10/82 Rev. 6 M.A. U. (Microsoft)
74;* Corrected problem with line numbers, and a problem
75;* with seeking for 0 chars.
76;*
77;* 03/30/83 Rev. 7 M.A. U. (Microsoft)
78;* Added patch area for bug fixing.
79;*
80;* 04/14/83 Rev. 8 M.A. U. (Microsoft)
81;* Made changes for Kanji characters. (ugh!)
82;*
83;* 12/17/84 Rev. 9 Zibo (Microsoft)
84;* Fix boundary case for buffer containing exact line
85;*
86;* V4.0 : 6/29/87 Russ W (IBM)
87;* Lines commented with ;AN000;
88;* Add support for IBM Parse service routines
89;* Add support for IBM Message Retriever Service Routines
90;* Add support for Code Page File Tags
91;* Made PROCs out of all labels that were targets of a call (not commented with AN000)
92;* Removed patch area for "bug fixing"
93;*
94;* V4.0 : 9/15/87 Bill L, (IBM)
95;* ;AN001; = DCR 201, changes to extended attributes support
96;* ;AN002; = PTM 1090
97;* ;AN003; = DCR 191
98;* ;AN004; = PTM 1630
99;* ;AN005; = PTM 1643, PTM 1675, PTM 1754
100;* ;AN006; = DBCS support
101;* ;AN007; = Optimizations to save disk space on ship diskettes
102;*
103;**********************************************************************
104
105;--------------------------
106;- MACRO DEFINITIONS
107;--------------------------
108BREAK MACRO subtitle
109 SUBTTL subtitle
110 PAGE
111ENDM
112
113
114;---------------------------;
115;- INCLUDE FILES ;
116;---------------------------;
117.xlist ;
118.xcref ;
119 INCLUDE SYSCALL.INC ;
120 INCLUDE sysmsg.inc ; ;AN000; Include message equates and MACROS
121 INCLUDE find.inc ; ;AN000; Include find equates and MACROS
122.list ;
123.cref ;
124;---------------------------;
125
126MSG_UTILNAME <FIND> ;AN000;
127
128;--------------------------
129;- EQUATES
130;--------------------------
131FALSE equ 0
132TRUE equ NOT FALSE
133
134CR equ 0dh ;A Carriage Return
135LF equ 0ah ;A Line Feed
136quote_char equ 22h ;A double quote character
137
138
139buffer_size equ 4096 ;file buffer size
140st_buf_size equ 128 ;string arg. buffer size
141fname_buf_size equ 64 ;file name buffer size
142
143
144;----- DOS EQUATES -----;
145STDIN equ 0 ;AN000; Handle
146STDOUT equ 1 ;AN000; Handle
147STDERR equ 2 ;AN000; Handle
148
149GetCPSW equ 03303h ;AN000; Int 021h function call
150GetExtAttr equ 05702h ;AN000; Int 021h function call
151SetExtAttr equ 05704h ;AN000; Int 021h function call
152
153ERROR_ACCESS_DENIED equ 5 ;AN000; Int 021h error return
154
155CPSWActive equ 1 ;AN000; Indicates Code Page support is active
156CPSWNotActive equ 0 ;AN000; Just the opposite
157
158ERRORLEVEL_ZERO equ 0 ;AN000; Termination error level
159ERRORLEVEL_ONE equ 1 ;AN000; Termination error level
160ERRORLEVEL_TWO equ 2 ;AN000; Termination error level
161
162;------------------------
163;- MESSAGE EQUATES
164;------------------------
165
166msg_file_not_found equ 2 ;AN000; File not found %s
167msg_access_denied equ 5 ;AN000; Access denied %s
168msg_read_error equ 30 ;AN000; Read error in %s
169msg_inv_num_parm equ 2 ;AN000; Invalid number of parameters
170msg_inv_parm equ 10 ;AN000; Invalid Parameter %s
171msg_required_missing equ 2 ;AN005; Required parameter missing
172msg_find equ 4 ;AN000; FIND:
173msg_code_page_mismatch equ 37 ;AN005; Code Page mismatch
174msg_switch equ 3 ;AN005; Invalid switch
175
176;-----------------------
177;-- Parser equates
178;-----------------------
179
180FarSW equ 0 ;AN000;
181DateSW equ 0 ;AN000;
182TimeSW equ 0 ;AN000;
183FileSW equ 1 ;AN000;
184CAPSW equ 1 ;AN000;
185CmpxSW equ 0 ;AN000;
186DrvSW equ 0 ;AN000;
187QusSW equ 1 ;AN000;
188NumSW equ 0 ;AN000;
189KeySW equ 0 ;AN000;
190SwSW equ 1 ;AN000;
191Val1SW equ 0 ;AN000;
192Val2SW equ 0 ;AN000;
193Val3SW equ 0 ;AN000;
194
195;------------------------
196; SUBLIST Equates
197;------------------------
198Left_Align equ 0 ;AN000; 00xxxxxx
199Right_Align equ 80h ;AN000; 10xxxxxx
200
201Char_Field_Char equ 0 ;AN000; a0000000
202Char_Field_ASCIIZ equ 10h ;AN000; a0010000
203
204Unsgn_Bin_Byte equ 11h ;AN000; a0010001 - Unsigned Binary to Decimal character
205Unsgn_Bin_Word equ 21h ;AN000; a0100001
206Unsgn_Bin_DWord equ 31h ;AN000; a0110001
207
208Sgn_Bin_Byte equ 12h ;AN000; a0010010 - Signed Binary to Decimal character
209Sgn_Bin_Word equ 22h ;AN000; a0100010
210Sgn_Bin_DWord equ 32h ;AN000; a0110010
211
212Bin_Hex_Byte equ 13h ;AN000; a0010011 - Unsigned Binary to Hexidecimal character
213Bin_Hex_Word equ 23h ;AN000; a0100011
214Bin_Hex_DWord equ 33h ;AN000; a0110011
215
216;------------------------------
217; EXTENDED ATTRIBUTE Equates
218;------------------------------
219File_Type_None equ 00000000b ;AN001; unspecified file type
220File_Type_Text equ 00100000b ;AN001; ASCII text file
221File_Type_Rtl equ 00100001b ;AN001; ASCII text file in RTL
222
223EAISBINARY equ 02h ;AN001; ea_type
224EASYSTEM equ 8000h ;AN001; ea_flags
225
226;---------------------------------------
227;-------------- CODE SEGMENT -----------
228;---------------------------------------
229
230code segment public
231 assume cs:code
232 assume ds:nothing
233 assume es:nothing
234 assume ss:stack
235
236 jmp start
237
238;
239;--------------------
240.xlist
241.xcref
242INCLUDE parse.asm
243.list
244.cref
245;--------------------
246
247 EXTRN heading:byte,heading_len:byte
248
249;*********************************
250;* Extended Attribute Structures *
251;*********************************
252querylist struc ;AN001; ;query general list
253qea_num dw 1 ;AN001;
254qea_type db EAISBINARY ;AN001;
255qea_flags dw EASYSTEM ;AN001;
256qea_namelen db ? ;AN001;
257qea_name db " " ;AN001;
258querylist ends ;AN001;
259
260cp_qlist querylist <1,EAISBINARY,EASYSTEM,2,"CP"> ;AN001; ;query code page attr.
261
262cp_list label word ;AN001; ;code page attr. get/set list
263 dw 1 ;AN001; ; # of list entries
264 db EAISBINARY ;AN001; ; ea type
265 dw EASYSTEM ;AN001; ; ea flags
266 db ? ;AN001; ; ea return code
267 db 2 ;AN001; ; ea name length
268 dw 2 ;AN001; ; ea value length
269 db "CP" ;AN001; ; ea name
270cp dw ? ;AN001; ; ea value (code page)
271cp_len equ ($ - cp_list) ;AN001;
272
273;-------Save area for Code Pages
274src_cp dw ? ;AN000; Save area for source code page
275tgt_cp dw ? ;AN000; Save area for target code page
276str_cp dw ? ;AN005; Save area for search string code page
277
278
279
280;-----------------------
281;----- Misc Data ------
282bufferDB db 6 dup(0) ;AN006;
283dbcs_off dw 0 ;AN006;
284dbcs_seg dw 0 ;AN006;
285dbcs_len dw 0 ;AN006;
286
287ccolon db ": "
288n1_buf db "["
289n2_buf db 8 dup(0) ;buffer for number conversion
290
291errlevel db ERRORLEVEL_ZERO ;AN000; Errrorlevel save area
292
293;----- OPTION FLAGS ----
294; If a flag is set (0ffh) then the option has been selected, if
295;reset (0) then it has been not. All options are reset initially.
296; NOTE: the order of this table has to remain consistent with the
297;options dispatch code. If any changes are made they have to
298;correspond with the code.
299
300opt_tbl:
301
302v_flag db FALSE ;AN000; Set to FALSE
303c_flag db FALSE ;AN000; Set to FALSE
304n_flag db FALSE ;AN000; Set to FALSE
305
306
307;----- LINE COUNTERS
308mtch_cntr dw 0 ;matched lines counter
309line_cntr dw 0 ;line counter
310
311;-------------------------------------------
312;- MESSAGE RETRIEVER SUBSTITUTION LIST
313;-------------------------------------------
314
315MSG_SERVICES <MSGDATA> ;AN000;
316
317sublist label dword ;AN000;
318sl_size db 11 ;AN000; SUBLIST Size, in bytes
319sl_res db 0 ;AN000; reserved
320sl_ptr_o dw ? ;AN000; Offset PTR to data item
321sl_ptr_s dw ? ;AN000; Segment PTR to data item
322sl_n db 0 ;AN000; n of %n
323sl_flag db ? ;AN000; Data-Type flags
324sl_maxw db 0 ;AN000; Max width
325sl_minw db 0 ;AN000; Min width
326sl_pad db ' ' ;AN000; Pad character
327
328
329parm db ? ;AN000; Save area for invalid parm
330cpsw_state db CPSWNotActive ;AN000; Save area indicating state of Code Page Support
331
332;******************************************************************************
333;* PARSER DATA STRUCTURES FOLLOW
334;******************************************************************************
335
336parms label byte ;AN000;
337 dw parmsx ;AN000; POINTER TO PARMS STRUCURE
338 db 1 ;AN000; DELIMITER LIST FOLLOWS
339 db 1 ;AN000; NUMBER OF ADDITIONAL DELIMITERS
340 db ";" ;AN000; ADDITIONAL DELIMITER
341
342parms1 label byte ;AN005;
343 dw parmsx1 ;AN005; POINTER TO PARMS STRUCURE
344 db 1 ;AN005; DELIMITER LIST FOLLOWS
345 db 1 ;AN005; NUMBER OF ADDITIONAL DELIMITERS
346 db ";" ;AN005; ADDITIONAL DELIMITER
347
348;------------------------------
349;- STRUCTURE TO DEFINE FIND SYNTAX REQUIREMENTS
350;------------------------------
351parmsx label word ;AN000;
352 db 1,2 ;AN000; THERE ARE BETWEEN 1 AND 2 POSITIONAL PARMS
353 dw pos1 ;AN000; POINTER TO POSITIONAL DEFINITION AREA
354 dw pos2 ;AN000; POINTER TO POSITIONAL DEFINITION AREA
355 db 1 ;AN000; THERE IS 1 SWITCH DEF AREA FOR "/V, /C, AND /N"
356 dw sw1 ;AN000; POINTER TO FIRST SWITCH DEFINITION AREA
357 dw 0 ;AN000; THERE ARE NO KEYWORDS IN FIND SYNTAX
358
359parmsx1 label word ;AN005;
360 db 0,0 ;AN005; THERE ARE BETWEEN 1 AND 2 POSITIONAL PARMS
361 db 1 ;AN005; THERE IS 1 SWITCH DEF AREA FOR "/V, /C, AND /N"
362 dw sw1 ;AN005; POINTER TO FIRST SWITCH DEFINITION AREA
363 dw 0 ;AN005; THERE ARE NO KEYWORDS IN FIND SYNTAX
364
365 ;------------------------------
366 ;- STRUCTURE TO DEFINE POSITIONAL PARM
367 ;------------------------------
368pos1 label word ;AN000;
369 dw 0080h ;AN000; QUOTED STRING, REQUIRED
370 dw 0000h ;AN000; NO CAPITALIZE
371 dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF
372 dw novals ;AN000; NO VALUE LIST
373 db 0 ;AN000; NO KEYWORDS
374
375 ;------------------------------
376 ;- STRUCTURE TO DEFINE POSITIONAL PARM
377 ;------------------------------
378pos2 label word ;AN000;
379 dw 0203h ;AN000; FILE NAME, OPTIONAL, REPEATS ALLOWED
380 dw 0001h ;AN000; CAPITALIZE BY FILE TABLE
381 dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF
382 dw novals ;AN000; NO VALUE LIST
383 db 0 ;AN000; NO KEYWORDS
384
385
386 ;------------------------------
387 ;- STRUCTURE TO DEFINE THE SWITCHES
388 ;------------------------------
389sw1 label word ;AN000;
390 dw 0 ;AN000; NO MATCH FLAGS
391 dw 2 ;AN005; capitalize
392 dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF
393 dw novals ;AN000; NO VALUE LIST
394 db 3 ;AN000; THREE SWITCHES IN FOLLOWING LIST
395n_swch db "/N",0 ;AN000;
396v_swch db "/V",0 ;AN000;
397c_swch db "/C",0 ;AN000;
398
399
400 ;------------------------------
401 ;- VALUE LIST DEFINITION FOR NO VALUES
402 ;------------------------------
403novals label word ;AN000;
404 db 0 ;AN000; VALUE LIST
405
406
407 ;------------------------------
408 ;- RETURN BUFFER FOR POSITIONAL PARAMETERS
409 ;------------------------------
410ret_buff label word ;AN000;
411rb_type db ? ;AN000; TYPE RETURNED
412rb_item_tag db ? ;AN000; SPACE FOR ITEM TAG
413rb_synonym dw ? ;AN000; ES:rb_synonym points to synonym
414rb_value_lo dw ? ;AN000; SPACE FOR VALUE
415rb_value_hi dw ? ;AN000; SPACE FOR VALUE
416
417
418
419
420did_file db FALSE ;AN004; if true then already processed a file
421got_eol db FALSE ;AN004; if false then possibly more filenames on command line
422got_filename db FALSE ;AN004; if true then parser found a filename on command line
423got_srch_str db FALSE ;AN000; if true then parser found search string on command line
424ordinal dw 0 ;AN000; parser ordinal
425crlf db CR,LF ;AN000;
426
427
428;
429;************************************************************
430;*
431;* SUBROUTINE NAME: main
432;*
433;* SUBROUTINE FUNCTION:
434;* Process the command line. If there are no errors, then open
435;* the specified files, search for string, display it to the
436;* standard output device.
437;*
438;* INPUT: Command line (described in program header)
439;*
440;* OUTPUT:
441;* Files will be opened and read in. Regardless of the command
442;* line parameters entered by the user, output will be written
443;* to the standard output device handle 1.
444;*
445;* NORMAL EXIT:
446;* File(s) opened (if not STDIN), read successfully, and closed.
447;* Display requested information.
448;*
449;* ERROR CONDITIONS:
450;* Incorrect DOS version
451;* Invalid number of parameters
452;* Syntax error
453;* Access denied
454;* File not found
455;* Invalid Parameter
456;* Read error in
457;*
458;* INTERNAL REFERENCES:
459;* bin2asc
460;* clr_cntrs
461;* is_prefix
462;* next_kchar
463;* print_count
464;* prout
465;* prt_err
466;* prt_err_2
467;* prt_file_name
468;* prt_lcntr
469;*
470;**************************************************************************
471
472 MSG_SERVICES <FIND.ctl,FIND.cla,FIND.cl1,FIND.cl2> ;AN000;
473 MSG_SERVICES <DISPLAYmsg,LOADmsg,CHARmsg,NOCHECKSTDIN> ;AN003; Make retriever services available
474START:
475
476 mov ax,cs ;load ES to the right area,
477 mov es,ax ;
478 mov ds,ax ;
479
480 call sysloadmsg ;AN000; Preload messages, Check DOS Version.
481 jnc Set_for_parse ;AN000; If no error, parse command line
482
483 call prt_find ;AN005;
484 call sysdispmsg ;AN005;
485
486 mov ah,Exit ;AN000; Terminate new way
487 mov al,0 ;AN000; Errorlevel 0 (Compatible!)
488 int 021h ;AN000; Bye bye!
489
490;-----------------------------------
491;- DOS version is ok. Parse cmd line
492;-----------------------------------
493Set_for_parse:
494 call get_dbcs_vector ;AN006; ;Get DOS dbcs table vector
495;
496 mov ah,GetCurrentPSP ;AN000; Get PSP address, returned in BX
497 int 021h ;AN000;
498 mov ds,bx ;AN000; Put PSP Seg in DS
499 mov si,081h ;AN000; Offset of command line in PSP
500 xor cx,cx ;AN000; Number of args processed so far = 0
501 mov cs:ordinal,cx ;AN000; init parser ordinal
502
503;--------------------------------------
504; See if there was nothing entered
505;--------------------------------------
506 cmp byte ptr ds:080h,0 ;AN000; Check length of command line,
507 jne p_parse ;AN005; Go process the parameters
508 mov ax,msg_inv_num_parm ;AN000; No parms, too bad!
509 mov dh,2 ;AN005; message class
510 call display_and_die ;AN000; Tell the unfortunate user
511p_parse:
512 mov cs:got_filename,FALSE ;AN004; input file default is STDIN
513
514 push cs ;A0005; ensure es is correct
515 pop es ;AN005;
516
517 call clr_cntrs ;AN005; set all counters to zero
518 mov cx,cs:ordinal ;AN005; init parser ordinal
519 call pre_parse ;AN005;
520PARSER:
521 push cs ;A0000; ensure es is correct
522 pop es
523
524 call clr_cntrs ; set all counters to zero
525 mov cx,cs:ordinal ;AN000; init parser ordinal
526 call parse ;AN000; Parse command line
527
528 push si ;AN000; Save ptr to remaining command line
529 push ds
530
531 push cs ;Load new DS with CS
532 pop ds
533 mov cs:ordinal,cx ;AN000; Save parser ordinal
534
535;---------------------
536; get filespec size
537;---------------------
538 mov cs:file_name_buf,di ;save buffer offset from parser
539 xor bx,bx ;AN000;indicate no save again
540 call get_length ;AN000;get filespec length
541 mov es:file_name_len,ax ;save the name length
542
543;---------------------
544;- Check current state of CPSW
545;---------------------
546save_src_cp:
547 mov ax,GetCPSW ;AN000; Get CPSW state, assume support is OFF
548 int 021h ;AN000; DL: 0=NotSupported,1=Supported
549 jc open_read ;AN000; If error, assume CPSW inactive
550 mov cs:cpsw_state,dl ;AN000; Save current state
551 and dl,dl ;AN007; ;AN000; If inactive, (same as CMP dl,0)
552 je open_read ;AN000; do nothing
553
554;-------Code Page Switching is loaded and active!
555;-------Save codepage of target handle ----------
556 mov bx,STDOUT ;AN000; For Standard output device
557 call get_cp ;AN000; Get the current codepage
558 jc open_read ;AN000; Error condition
559 mov ax,cs:cp ;AN000; Save target code page
560 mov cs:tgt_cp,ax ;AN000; for later reference
561 xor bx,bx ;AN007; ;AN005; bx=STDIN. For search string
562 call get_cp ;AN005; Get the code page
563 jc open_read ;AN005; Error condition
564 mov ax,cs:cp ;AN005; Save code page value
565 mov cs:str_cp,ax ;AN005; ..
566
567;---------------------
568;- OPEN FILE FOR READING
569;---------------------
570open_read:
571 push cs ;Load new DS with CS
572 pop ds
573 cmp cs:got_filename,TRUE ;AN004; using STDIN
574 je o_cont ;AN004; no, open the file
575 xor ax,ax ;AN007; ;AN004; file handle (ax) = STDIN
576 jmp short cp_check ;AN007; ;AN004; skip open of file
577o_cont: ;AN004;
578 mov dx,cs:file_name_buf ;AC000;addrss. of the file name
579openit:
580 mov ah,open
581 mov al,0 ;file open for reading
582 int 021h ;call the DOS
583 ljc do_open_error ;AN000;
584;-------Open was successful. Make sure codepages are the same
585cp_check:
586 cmp cs:cpsw_state,CPSWNotActive ;AN000; Is Code Page support active
587 je say_name ;AN000; No, continue
588
589 push ax ;AN000; Save source handle
590 mov bx,ax ;AN000; Source handle in BX
591 call get_cp ;AN000; Get codepage of source file
592
593 mov ax,cs:cp ;AN000; Place source CP in ax
594 cmp ax,cs:str_cp ;AN005; search string code page = src file code page ?
595 je c_cont ;AN005; yes, they are the same, ok
596 and ax,ax ;AN007; ;AN005; src filename cp = 0
597 je c_cont ;AN005; yes, this cp=0 is ok.
598 mov ax,msg_code_page_mismatch ;AN005; Error, code page mismatch
599 mov dh,1 ;AN005; message class
600 call display_and_die ;AN005; bye!
601c_cont:
602 cmp ax,cs:tgt_cp ;AN000; Is same as target cp ?
603 je cp_match ;AN000; Yes? Do nothing
604
605 mov bx,STDOUT ;AN000; Standard output device
606 call set_cp ;AN000; Set codepage to that of source
607cp_match:
608 pop ax ;AN000; Restore handle
609;---------------------
610;- PRINT FILE NAME
611;---------------------
612say_name:
613 push ax ;save file handle
614 cmp cs:got_filename,FALSE ;AN004; using STDIN
615 je xx1 ;AN004; yes, don't print a filename
616 mov dx,offset heading
617 mov cl,cs:heading_len
618 xor ch,ch
619 call prout
620
621 mov dx,cs:file_name_buf ;AC000;
622 mov cx,cs:file_name_len
623 call prout
624
625 cmp cs:c_flag,TRUE ;count only flag set?
626 je xx1
627
628 mov dx,offset crlf
629 mov cx,2
630 call prout
631xx1:
632 pop ax
633
634;---------------------
635;- Fill Buffer for Matching
636;---------------------
637fill:
638 mov bx,ax ;retrieve handle
639refill:
640 mov dx,offset buffer ;data buffer addrss.
641 mov cx,buffer_size
642 mov ah,read
643 int 021h
644 jnc no_read_error ;if carry then read error
645 jmp read_error
646no_read_error:
647 or ax,ax ;if ax=0 then all done
648 jnz Truncate
649DoNullRead:
650 cmp cs:c_flag,TRUE ;count only flag set?
651 jne sj2
652 call print_count
653sj2:
654 and bx,bx ;Using STD IN?
655 jnz regular
656 jmp foo ;if so: all done, exit
657regular:
658 mov ah,close ;otherwise close the file
659 int 021h
660 jmp scan_rest ;get another file
661
662do_open_error:
663 jmp open_error ;AN000;
664;---------------------------
665; We have read in an entire buffer. Scan for a ^Z and terminate the buffer
666; there. Change only CX
667;---------------------------
668Truncate:
669 push di
670 push cx
671 push es
672 mov di,dx
673 mov cx,ax
674 mov ax,ds
675 mov es,ax
676 mov al,1Ah
677 CLD
678 repnz scasb
679;---------------------------
680; If zero is set, the the previous character is a ^Z. If it is reset then
681; the previous character is the end of buffer. With ^Z, we back up over the
682; char.
683;---------------------------
684 jnz chop
685 dec di
686chop:
687 mov ax,di
688 sub ax,dx ; get true length of buffer
689 pop es
690 pop cx
691 pop di
692 or ax,ax
693 jz DoNullRead
694
695;---------------------------
696;----- MATCH ROUTINE
697;---------------------------
698;Note: If input is being taken from a file the stack contains
699; (from top to bottom):
700; - Pointer to the next command in the command line
701; - Pointer to the program segment prefix (to be loaded into
702; DS to access the command line.
703; if the input is from the standard input then NONE of it will be
704; in the stack.
705;---------------------------
706
707go_match:
708 push bx ;save the file handle
709 mov bp,offset buffer ;ptr to first line of file
710;---------------------------
711; At this point we must check to make sure there is AT LEAST one LF in the
712; buffer. If there is not, then we must insert one at the end so we
713; don't get stuck trying to get one complete line in the buffer when
714; we can't cause the buffer ain't big enough.
715;---------------------------
716 push ax ; Save true buffer size
717 mov cx,ax ; scan whole buffer
718 mov al,LF ; for a LF
719 mov di,bp ; start of buffer
720 repnz scasb
721 pop ax ; recover buffer size
722 mov di,ax ;displacement from beg of buffer
723 jnz last_line ; No line feeds, must insert one
724;---------------------------
725; Check to see if we reached EOF (return from READ less than buffer_size).
726; If EOF we must make sure we end with a CRLF pair.
727;---------------------------
728 cmp ax,buffer_size-1 ;last line of the file?
729 jg no_last_line ;nope
730last_line: ;if yes, add a CRLF just in case
731 mov bx,bp
732 cmp byte ptr[bx+di-1],LF ;finished with a LF?
733 je no_last_line ;yes, it's an OK line.
734 mov byte ptr[bx+di],CR ;put a CR at the end of the data
735 inc di
736 mov byte ptr[bx+di],LF ;put a LF ...
737 inc di
738
739no_last_line:
740 push di ;save the # of chars. in the buffer
741 push bp
742 mov dx,cs:st_length ;length of the string arg.
743 dec dx ;adjust for later use
744 jmp short try_again
745
746more_stuff_o:
747 jmp more_stuff
748
749;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------;
750;Note: at this point the stack contains (from top to bottom):
751; - Stuff mentioned before
752; - File Handle
753; - Number of chars. left in the buffer from the next line.
754; - Addrs. of the next line in the buffer.
755;
756; plus, DX has the adjusted length of the string argument.
757;
758; We are about to begin scanning a line. We start by determining if there is
759; a complete line in the buffer. If so, we scan for the char. If NOT, we go
760; and grab new info.
761;---------------------------
762try_again:
763 pop bp ;addrs. of next line in the buffer
764 mov di,bp ;points to beg. of a line
765 pop cx ;get # of chars left in the buffer
766 mov bx,cx ;save in case a non-complete line
767 mov al,LF ;search for a Line Feed
768 jcxz more_stuff_o ;no chars left in buffer
769 repnz scasb
770 jnz more_stuff_o ;no full line left in buffer
771 push cx ;save chars left in buffer
772 push di ;points to beg. of next line
773 mov cx,di
774 sub cx,bp ;length of the current line
775 mov bx,cx ;save in case it has a match
776 dec cx ;Discount the LF we found
777 cmp byte ptr ES:[DI-2],CR ; Is there a CR to discount too?
778 jnz NO_SECOND_DEC ; No there is not.
779 dec cx ;CR character discounted
780NO_SECOND_DEC:
781 inc cs:line_cntr ;increment line counter
782 jcxz try_again_opt ;if line empty go to next line
783 mov di,bp ;pointer to the beg. of current line
784another_char:
785;---------------------------
786; On entry:
787; BX line length
788; CX adjusted line length
789; DX adjusted string argument length
790; DI points to beg. of line
791;---------------------------
792 push dx ;save for next line
793lop:
794 pop dx
795 push dx
796 inc dx ;different algorithm!
797 mov si,offset st_buffer ;pointer to beg. of string argument
798
799comp_next_char:
800 push di
801 mov di,si
802 call is_prefix ;check for a prefix char
803 pop di
804 jnc nopre
805 lodsw
806 cmp cx,1 ; Can not compare a two byte char
807 jbe try_again_opt1 ; if there is only one available
808 cmp ax,word ptr [di]
809 jz kmatch1
810 jmp short back_up ;AN007;
811
812nopre:
813 lodsb
814 cmp al,byte ptr [di]
815 jz kmatch
816back_up:
817 pop ax ; Original length of comp string
818 push ax
819 inc ax
820;---------------------------
821 ; Our match failed IN THE MIDDLE of the string (partial match). We need
822 ; to back up in the line to the NEXT char after the one which matched
823 ; the first char of the search string and try again. The amount to
824 ; back up to where we started is ax-dx (the result MAY be 0, this is OK).
825 ; we then need to skip ONE char in the line.
826;---------------------------
827 sub ax,dx ; AX = AX-DX
828 sub di,ax ; Do the back up.
829 add cx,ax ; restore count too!
830 call next_kchar ;no match, advance di to next kanji
831 jc try_again_opt1 ;not enough chars left in line
832 jmp short lop ;try another char in line
833
834try_again_opt1:
835 pop dx
836 jmp short try_again_opt ;AN007;
837
838
839kmatch1:
840 dec dx ;last char had prefix so it was
841 ; long.
842kmatch:
843 dec dx
844 jz a_matchk ; no chars left: a match!
845 call next_kchar
846 jc try_again_opt1
847 jmp comp_next_char ; loop if chars left in arg.
848
849a_matchk:
850 pop dx
851 cmp cs:v_flag,TRUE ;is flag set?
852 jne prt_line ;no, print the line
853 jmp try_again
854
855;---------------------------
856;- NO MATCH: CHECK FOR THE v OPTION
857;---------------------------
858try_again_opt:
859 cmp cs:v_flag,TRUE ;is flag set?
860 jne try_again ;no goto next line
861
862;---------------------------
863;- PRINT THE LINE WITH THE MATCH
864;Note: at this point the stack contains (top to bottom)
865; - Stuff mentioned before
866;
867; plus, BP points to begginig of the current line, BX has the length
868;of the current line including the CRLF, and DX the adjusted length of
869;the string argument.
870;---------------------------
871
872prt_line:
873 cmp cs:c_flag,TRUE ;is count only flag set?
874 jne no_c_flg
875 inc cs:mtch_cntr ;yes, increment counter
876 jmp try_again
877
878no_c_flg:
879 push dx ;save the adjusted string arg. length
880 cmp cs:n_flag,TRUE ;is line number flag set?
881 jne no_n_flg
882 call prt_lcntr
883no_n_flg:
884 mov dx,bp
885 mov cx,bx
886 call prout
887 pop dx ;restore
888 jmp try_again
889
890;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------;
891; The scanning routines have detected that the buffer does not
892;contain a full line any more. More lines have to be read into the
893;buffer. But first perform a seek on the file in order to re-read
894;the non-complete line into the begining of the buffer.
895; Uppon entry BP contains points to the begining of the non-complete
896;line, and BX has the number of characters left in the buffer.
897; The Stack contains (top to bottom):
898; - Pointer to the next command in the command line
899; - Pointer to the program segment prefix (to be loaded into
900; DS to access the command line).
901; - File handle.
902
903more_stuff:
904 mov dx,bx ;get chars left in buffer
905 pop bx ;get the handle
906 or dx,dx ;are there 0 left?
907 jz no_seek ;yes, do not seek
908 neg dx ;form two's complement
909 mov cx,-1
910 mov al,1 ;seek from the current position
911 mov ah,lseek ;seek on file
912 int 021h
913 jc read_error
914no_seek:
915 jmp refill ;no errors: refill the buffer
916read_error:
917 and bx,bx ;AN007; ;Using STD IN?
918 je foo ;if so: all done, exit
919 mov ah,close ;close the file
920 int 021h
921;---------------
922;------ Set message number and go display it
923
924 mov ax,msg_read_error ;AN000; Read error message
925 jmp short r_error ;AN007;
926
927;---------------------
928;- PRINT ERRORS
929;---------------------
930open_error:
931 cmp ax,ERROR_ACCESS_DENIED ;AN000;
932 jnz DoNorm
933
934 mov ax,msg_access_denied ;AN000; Message for Access Denied
935 jmp short r_error ;AN007; ;AN000; Do the rest
936
937DoNorm: ;AN000;
938 mov ax,msg_file_not_found ;AN000; Message for File Not Found
939
940r_error:
941 call prt_find ;AN005;
942 mov cs:sl_ptr_s,ds ;AN000; Save segment of subst text
943 mov cx,cs:file_name_buf ;AN000;
944 mov cs:sl_ptr_o,cx ;AN000; Save offset of subst text
945 mov cs:sl_flag,left_align+char_field_ASCIIZ ;AN000; Type of insertion text
946 mov bx,STDERR ;AN000; Sent to STD OUT
947 mov cx,1 ;AN000; One substitution string
948 mov dh,1 ;AN000; Its a utility message
949
950 call display_msg ;AN000; Display rror message
951
952;---------------------
953;- SCAN THE REST OF THE COMMAND LINE
954;---------------------
955scan_rest:
956 pop ds ;restore pointer to comm. line
957 pop si ;restore pointer to next comm.
958 mov cs:did_file,TRUE ;AN004; tell parser we did a file, so if it doesn't find another, ok!
959 cmp cs:got_eol,TRUE ;AN004; Check if nothing left on command line
960 je foo ;AN004; no, nothing left on command line, exit
961 jmp parser
962
963foo:
964 mov cs:errlevel,ERRORLEVEL_ZERO ;AN000; Proper code
965 call terminate ;AN000; reset codepage and terminate
966
967
968;--------------------------
969; Clear Counters
970;--------------------------
971clr_cntrs proc near
972 mov byte ptr cs:mtch_cntr,0
973 mov byte ptr cs:line_cntr,0
974 ret
975clr_cntrs endp
976
977
978;--------------------------
979; Print Count of Matched lines
980; Modifies: AX,CX,DX and DI
981;--------------------------
982print_count proc near
983 push bx ;save handle
984 and bx,bx ;AN007; ;using STDIN?
985 jz sj3 ;if so do not print file name
986
987 mov dx,offset ccolon
988 mov cx,2
989 call prout ;print colon
990sj3:
991 mov ax,cs:mtch_cntr
992 mov di,offset n2_buf ;buffer for characters
993 call bin2asc ;convert to ascii
994 mov dx,offset n2_buf
995 call prout ;print the number
996 mov dx,offset crlf
997 mov cx,2
998 call prout ;print an end of line
999 pop bx
1000 ret
1001print_count endp
1002
1003;--------------------------
1004; Print relative line number
1005
1006; Modifies: AX,CX and DI
1007;--------------------------
1008prt_lcntr proc near
1009 push bx
1010 push dx
1011 mov ax,cs:line_cntr
1012 mov di,offset n2_buf
1013 call bin2asc
1014 mov byte ptr[di],"]"
1015 inc cx
1016 inc cx
1017 mov dx,offset n1_buf
1018 call prout
1019 pop dx
1020 pop bx
1021 ret
1022prt_lcntr endp
1023
1024;--------------------------
1025; Print string to STDOUT
1026;--------------------------
1027prout proc near
1028 mov bx,STDOUT
1029 mov ah,write
1030 int 021h
1031 ret
1032prout endp
1033
1034;--------------------------
1035; Binary to Ascii conversion routine
1036; Entry:
1037; AX Binary number
1038; DI Points to one past the last char in the
1039; result buffer.
1040; Exit:
1041; Result in the buffer MSD first
1042; CX Digit count
1043; Modifies:
1044; AX,BX,CX,DX and DI
1045;--------------------------
1046bin2asc proc near
1047 mov bx,0ah
1048 xor cx,cx
1049go_div:
1050 inc cx
1051 cmp ax,bx
1052 jb div_done
1053 xor dx,dx
1054 div bx
1055 add dl,'0' ;convert to ASCII
1056 push dx
1057 jmp short go_div
1058
1059div_done:
1060 add al,'0'
1061 push ax
1062 mov bx,cx
1063deposit:
1064 pop ax
1065 stosb
1066 loop deposit
1067 mov cx,bx
1068 ret
1069bin2asc endp
1070
1071;--------------------------
1072; CAPIALIZES THE CHARACTER IN AL
1073; entry:
1074; AL has the character to Capitalize
1075; exit:
1076; AL has the capitalized character
1077; modifies:
1078; AL
1079;--------------------------
1080;make_caps proc near
1081; cmp al,'a'
1082; jb no_cap
1083; cmp al,'z'
1084; jg no_cap
1085; and al,0dfh
1086;no_cap:
1087; ret
1088;make_caps endp
1089;
1090
1091
1092;--------------------------
1093; ADVANCE POINTER TO NEXT KANJI CHARACTER
1094; entry: DI points to a Kanji string
1095; CX length in bytes of the string
1096; exit: DI points to next Kanji char
1097; CX has number of bytes left
1098; modifies: AX
1099;--------------------------
1100next_kchar proc near
1101 jcxz no_kleft
1102 call is_prefix
1103 jnc no_p
1104 inc di
1105 dec cx
1106 jcxz no_kleft ; for insurance
1107no_p:
1108 inc di
1109 dec cx
1110 clc
1111 ret
1112
1113no_kleft:
1114 stc
1115 ret
1116next_kchar endp
1117
1118;--------------------------
1119; Get DOS dbcs table vector
1120; entry: none
1121; exit: none
1122; modifies: none
1123;--------------------------
1124get_dbcs_vector proc near ;AN006;
1125 push es ;AN006;
1126 push di ;AN006;
1127 push ax ;AN006;
1128 push bx ;AN006;
1129 push cx ;AN006;
1130 push dx ;AN006;
1131;
1132 mov ax,cs ;AN006; ;segment of return buffer
1133 mov es,ax ;AN006;
1134 mov di,offset bufferDB ;AN006; ;offset of return buffer
1135 mov ah,65h ;AN006; ;get extended country info
1136 mov al,07h ;AN006; ;get DBCS environment table
1137 mov bx,0ffffh ;AN006; ;use active code page
1138 mov cx,5 ;AN006; ;number of bytes returned
1139 mov dx,0ffffh ;AN006; ;default country ID
1140 int 21h ;AN006; ;DOS function call,vector returned
1141 ;AN006; ; in ES:DI
1142 inc di ;AN006; ;skip over id byte returned
1143 mov ax,word ptr es:[di] ;AN006; ;get offset of DBCS table
1144 mov cs:dbcs_off,ax ;AN006; ;save it
1145;
1146 add di,2 ;AN006; ;skip over offset to get segment
1147 mov bx,word ptr es:[di] ;AN006; ;get segment of DBCS table
1148 mov cs:dbcs_seg,bx ;AN006; ;save it
1149;
1150 mov di,ax ;AN006; ;Point to DBCS table to get length
1151 mov es,bx ;AN006;
1152 mov ax,word ptr es:[di] ;AN006;
1153 mov cs:dbcs_len,ax ;AN006;
1154 add cs:dbcs_off,2 ;AN006; ;change offset to point to table
1155;
1156 pop dx ;AN006;
1157 pop cx ;AN006;
1158 pop bx ;AN006;
1159 pop ax ;AN006;
1160 pop di ;AN006;
1161 pop es ;AN006;
1162;
1163 ret ;AN006;
1164get_dbcs_vector endp ;AN006;
1165
1166
1167;--------------------------
1168; FIND OUT IS THE BYTE IS A KANJI PREFIX
1169; entry: DI points to a kanji string
1170; exit: Carry set if it is a kanji prefix
1171; modifies: AX
1172;--------------------------
1173is_prefix proc near ;AN006;
1174 push es
1175 push si
1176 push ax
1177;
1178 mov si,cs:dbcs_off ;ES:SI -> DOS dbcs table
1179 mov ax,cs:dbcs_seg
1180 mov es,ax
1181;
1182 mov al,byte ptr cs:[di] ;get first byte of string
1183;
1184; Two consecutive 00 bytes signifies end of table
1185;
1186
1187is_loop:
1188 cmp word ptr es:[si],00h ;Check for two consecutive 00 bytes
1189 jne is_next1 ;no, continue
1190 clc ;clear carry - byte is not lead byte of db char
1191 jmp short is_exit ;AN007; ;yes, found them, quit
1192
1193;
1194; Check if byte is within range values of DOS dbcs table
1195;
1196
1197is_next1:
1198 cmp al,byte ptr es:[si] ;is byte >= first byte in range?
1199 jae is_next2 ;yes, continue
1200 jmp short is_again ;AN007; ;no, loop again
1201
1202is_next2:
1203 cmp al,byte ptr es:[si+1] ;is byte <= last byte in range?
1204 jbe is_found ;yes, found a lead byte of db char
1205
1206is_again:
1207 add si,2 ;no, increment ptr to next range
1208 jmp is_loop
1209
1210is_found:
1211 stc ;byte is lead byte of db char, set carry
1212
1213is_exit:
1214 pop ax
1215 pop si
1216 pop es
1217;
1218 ret
1219is_prefix endp
1220
1221
1222;
1223;---------------------
1224;- Terminate process
1225;---------------------
1226terminate proc near ;AN000;
1227 mov ah,exit ;AN000; Terminate function call
1228 mov al,cs:errlevel ;AN000; Errorlevel placed in AL
1229 int 021h ;AN000; Terminate
1230 ret ;AN000; Meaningless return
1231terminate endp ;AN000;
1232
1233;
1234;************************************************************
1235;*
1236;* SUBROUTINE NAME: set_cp
1237;*
1238;* FUNCTION: Sets the cp of the handle in bx to the cp in LIST structure
1239;*
1240;* INPUT:
1241;* BX = handle
1242;* cp_list.cp = code page to set for the file handle in BX
1243;*
1244;* OUTPUT:
1245;* Codepage will be set to that requested, or an error will be
1246;* returned in AX with carry flag set.
1247;*
1248;************************************************************
1249set_cp proc near ;AN000;
1250 mov ax,SetExtAttr ;AN000; Set target codepage to that of source
1251 mov di,offset cp_list ;AC001; Input buffer address
1252 int 021h ;AN000; Call DOS
1253 ret ;AN000; Return to caller
1254set_cp endp ;AN000;
1255
1256
1257
1258;************************************************************
1259;*
1260;* SUBROUTINE NAME: get_cp
1261;*
1262;* FUNCTION: Gets the cp of the handle in bx
1263;*
1264;* INPUT:
1265;* BX = handle
1266;*
1267;* OUTPUT:
1268;* Codepage for the file handle in bx will be returned in
1269;* the CP_LIST.CP structure, or an error will be returned in
1270;* AX with carry flag set.
1271;*
1272;************************************************************
1273get_cp proc near ;AN000;
1274 push ds ;AN005;
1275
1276 push cs ;AN005;
1277 pop ds ;AN005;
1278
1279 mov ax,GetExtAttr ;AN000; Get codepage
1280 mov di,offset cp_list ;AN000; Input buffer address
1281 mov si,offset cp_qlist ;AN001; which ea to select
1282 mov cx,cp_len ;AN001; buffer length
1283 int 021h ;AN000; Call to DOS
1284
1285 pop ds ;AN005;
1286 ret ;AN000; Return to caller
1287get_cp endp ;AN000;
1288
1289
1290;
1291;************************************************************
1292;*
1293;* SUBROUTINE NAME: display_msg
1294;*
1295;* SUBROUTINE FUNCTION:
1296;* Display the requested message to the specified handle
1297;*
1298;* INPUT:
1299;* 1) AX = Number of the message to be displayed.
1300;* 2) BX = Handle to be written to.
1301;* 3) DH = Code indicating message class
1302;*
1303;* OUTPUT:
1304;* The message corresponding to the requested msg number will
1305;* be written to the requested handle.
1306;*
1307;* NORMAL EXIT:
1308;* Message will be successfully written to requested handle.
1309;*
1310;* ERROR EXIT:
1311;* None. Note that theoretically an error can be returned from
1312;* SYSDISPMSG, but there is nothing that the application can do.
1313;*
1314;* INTERNAL REFERENCES:
1315;* System Display Message service routines
1316;*
1317;* EXTERNAL REFERENCES:
1318;* None
1319;*
1320;************************************************************
1321display_msg proc near ;AN000;
1322 push ds ;AN000; Save DS
1323 push cs ;AN000; Substitution list segment
1324 pop ds ;AN000;
1325 mov si,offset sublist ;AN000; Substitution list offset
1326 ; mov dh,-1 ;AN000; Message class
1327 ; 1=DOS Extended error
1328 ; 2=DOS Parse error
1329 ; -1=Utility message
1330 mov dl,0 ;AN000; DOS INT 21H function number to use for input
1331 ; 00H=No input, 01H=Keyboard input,
1332 ; 07H=Direct Console Input Without Echo,
1333 ; 08H=Console Input Without Echo, 0AH=Buffered Keyboard Input
1334 call SYSDISPMSG ;AN000; AX=Extended key value if wait for key
1335 ; jnc disp_done ;AN000; If CARRY SET then registers will contain extended error information
1336 ; AX - Extended error Number
1337 ; BH - Error Class
1338 ; BL - Suggested action
1339 ; CH - Locus
1340disp_done: ;AN000;
1341 pop ds ;AN000; Restore DS
1342 ret ;AN000;
1343display_msg ENDP ;AN000;
1344
1345 PAGE
1346;************************************************************
1347;*
1348;* SUBROUTINE NAME: parse
1349;*
1350;* SUBROUTINE FUNCTION:
1351;* Call the DOS PARSE Service Routines to process the command
1352;* line. Search for valid switches (/N, /V, and /C) and take
1353;* appropriate action for each. Extract the search string.
1354;*
1355;* INPUT: DS:SI points to string to parse
1356;* ES:DI parser parms
1357;*
1358;* OUTPUT: ES:DI points to filespec for text search
1359;*
1360;* NORMAL EXIT:
1361;*
1362;* If /V, /C, or /N entered, set appropriate flag.
1363;* Save the search string.
1364;*
1365;* ERROR EXIT:
1366;*
1367;* If user enters any invalid parameter or switch, then this
1368;* routine will display an error message and terminate with
1369;* errorlevel 1.
1370;*
1371;************************************************************
1372EOL equ -1 ;AN000; Indicator for End-Of-Line
1373NOERROR equ 0 ;AN000; Return Indicator for No Errors
1374SYNTAX equ 9 ;AN000; Syntax error from parser
1375
1376SWITCH equ 3 ;AN000;
1377FILESPEC equ 5 ;AN000;
1378QUOTED_STRING equ 9 ;AN000;
1379
1380parse proc near ;AN000;
1381;--------------------------------------
1382; address of command line in DS:SI
1383;--------------------------------------
1384;------------------------------------------
1385;- Look for the search string and switches
1386;------------------------------------------
1387parse_loop: ;AN000;
1388 mov di,offset parms ;AN000; Address of parse control block at ES:DI
1389 xor dx,dx ;AN000; Reserved
1390 call sysparse ;AN000; Parse parm at DS:SI
1391 cmp ax,EOL ;AN000; Are we at End Of Line ??
1392 jne p_next ;AN004; No eol found
1393 mov cs:got_eol,TRUE ;AN004; no more filenames to get!
1394 cmp cs:did_file,TRUE ;AN004; did we do a file already ?
1395 lje doexit ;AN004; yes, exit
1396 jmp end_parse ;AN004; Yes, done here
1397p_next: ;AN004; continue
1398 and ax,ax ;AN007; ;AN000; Was there an error?
1399 je CONT2 ;AN000; No, continue processing
1400
1401 mov dh,2 ;AN005; Its a PARSE message
1402 call display_and_die ;AN005;
1403CONT2: ;AN000; Something valid was entered
1404 cmp cs:rb_type,QUOTED_STRING ;AN000; Is it a quoted string ?
1405 je its_a_quoted_string ;AN000; Yes, go process it
1406 cmp cs:rb_type,FILESPEC ;AN000; Is it a filespec?
1407 jne cont3 ;AN000;
1408 mov di,cs:rb_value_lo ;AN000; Look for another
1409 mov cs:got_filename,TRUE ;AN004; got a filename
1410 jmp short end_parse ;AN007; ;AN000; Look for another
1411cont3:
1412 cmp cs:rb_type,SWITCH ;AN000; Is it a switch ?
1413 je its_a_switch ;AN000; Yes, go process it
1414 mov ax,msg_inv_parm ;AN000; None of above, too bad
1415 mov dh,2 ;AN005; message class
1416 call display_and_die ;AN000; Tell the poor user and terminate
1417
1418;-----------------------------
1419;- The search string was entered
1420;-----------------------------
1421its_a_quoted_string: ;AN000; Found a quoted string
1422 cmp cs:got_srch_str,TRUE ;AN000; Do we already have one?
1423 jne its_ok ;AN000; No, it's ok
1424 mov ax,msg_inv_parm ;AN000; Yes, Invalid parm!
1425 mov dh,2 ;AN005; message class
1426 call display_and_die ;AN000; Tell user and die gracefully
1427its_ok: ;AN000;
1428 mov di,cs:rb_value_lo ;AN000; Get pointer to it
1429 mov bx,offset st_buffer ;AN000; save buffer offset
1430 call get_length ;AN000; get string length
1431 mov cs:st_length,ax ;AN000; save length
1432 mov cs:got_srch_str,TRUE ;AN000; Indicate that we have it
1433 jmp parse_loop ;AN000;
1434
1435;-----------------------------
1436;- A valid switch was entered
1437;-----------------------------
1438its_a_switch: ;AN000;
1439 mov bx,cs:rb_synonym ;AN000; Get offset of switch entered
1440 cmp bx,offset n_swch ;AN000; Is it the /N switch?
1441 jne chek_v ;AN000: Yes, process it.
1442 jmp parse_loop ;AN000; Look for another
1443chek_v: ;AN000;
1444 cmp bx,offset v_swch ;AN000; Is it the /N switch?
1445 jne chek_c ;AN000: Yes, process it.
1446 jmp parse_loop ;AN000; Look for another
1447chek_c: ;AN000;
1448 cmp bx,offset c_swch ;AN000; Is it the /N switch?
1449 jne whoops ;AN000: Yes, process it.
1450 jmp parse_loop ;AN000; Look for another
1451whoops: ;AN000; None of the above (can we ever get here?)
1452 mov ax,msg_switch ;AN000; Invalid parameter
1453 mov dh,2 ;AN005; message class
1454 call display_and_die ;AN000; Yes, tell the poor user and terminate
1455
1456end_parse: ;AN000; A filename should be next
1457 cmp cs:got_srch_str,TRUE ;AN000; Do we already have one?
1458 je rett ;AN000;
1459 mov ax,msg_required_missing ;AN005;
1460 mov dh,-1 ;AN005; message class
1461 call display_and_die ;AN000; Yes, tell the poor user and terminate
1462rett: ;AN000;
1463 ret ;AN000;
1464
1465doexit:
1466 mov cs:errlevel,ERRORLEVEL_ZERO;AN000; Proper code
1467 call terminate ;AN000; reset codepage and terminate
1468
1469parse endp ;AN000;
1470
1471
1472;------------------------------------
1473;-
1474;- Procedure name: pre_parse
1475;-
1476;- Purpose: parse for all switches now
1477;- so that they can be applied for
1478;- all filenames on command line.
1479;-
1480;- INPUT: none
1481;-
1482;------------------------------------
1483pre_parse proc near ;AN005;
1484 push ax ;AN005;
1485 push bx ;AN005;
1486 push cx ;AN005;
1487 push dx ;AN005;
1488 push di ;AN005;
1489 push si ;AN005;
1490 push es ;AN005;
1491 push ds ;AN005;
1492;
1493pp_loop: ;AN005;
1494 mov di,offset parms1 ;AN005; Address of parse control block at ES:DI
1495 xor dx,dx ;AN005; Reserved
1496 call sysparse ;AN005; Parse parm at DS:SI
1497
1498 cmp ax,EOL ;AN005; Are we at End Of Line ??
1499 je pp_end ;AN005; No eol found
1500
1501 cmp ax,SWITCH ;AN005; invalid switch ?
1502 jne pp_next ;AN005; no
1503; error
1504 mov ax,msg_switch ;AN005; Invalid switch
1505 mov dh,2 ;AN005; message class
1506 call display_and_die ;AN005; Yes, tell the poor user and terminate
1507pp_next:
1508 and ax,ax ;AN007; ;AN005; Was there an error?
1509 jne pp_loop ;AN005; No, continue processing
1510
1511 cmp cs:rb_type,SWITCH ;AN005; Is it a switch ?
1512 jne pp_loop ;AN005;
1513
1514; got a switch
1515 mov bx,cs:rb_synonym ;AN005; Get offset of switch entered
1516 cmp bx,offset n_swch ;AN005; Is it the /N switch?
1517 jne pp_chek_v ;AN005: Yes, process it.
1518 mov cs:n_flag,TRUE ;AN005; Set the corresponding flag
1519 jmp pp_loop ;AN005; Look for another
1520pp_chek_v: ;AN005;
1521 cmp bx,offset v_swch ;AN005; Is it the /N switch?
1522 jne pp_chek_c ;AN005: Yes, process it.
1523 mov cs:v_flag,TRUE ;AN005; Set the corresponding flag
1524 jmp pp_loop ;AN005; Look for another
1525pp_chek_c: ;AN005;
1526 cmp bx,offset c_swch ;AN005; Is it the /N switch?
1527 jne pp_error ;AN005: Yes, process it.
1528 mov cs:c_flag,TRUE ;AN005; Set the corresponding flag
1529 jmp pp_loop ;AN005; Look for another
1530
1531pp_error: ;AN005; None of the above (can we ever get here?)
1532 mov ax,msg_switch ;AN005; Invalid parameter
1533 mov dh,2 ;AN005; message class
1534 call display_and_die ;AN005; Yes, tell the poor user and terminate
1535
1536pp_end: ;AN005; A filename should be next
1537 pop ds ;AN005;
1538 pop es ;AN005;
1539 pop si ;AN005;
1540 pop di ;AN005;
1541 pop dx ;AN005;
1542 pop cx ;AN005;
1543 pop bx ;AN005;
1544 pop ax ;AN005;
1545;
1546 ret ;AN005;
1547pre_parse endp ;AN005;
1548
1549
1550;------------------------------------
1551;-
1552;- Procedure name: prt_find
1553;-
1554;- Purpose: When FIND is used as a filter,
1555;- then display error messages with the
1556;- prefix: "FIND: ".
1557;-
1558;- INPUT: none
1559;-
1560;------------------------------------
1561prt_find proc near ;AN005;
1562 cmp cs:got_filename,TRUE ;AN005; Check if should print "FIND:"
1563 je prt_ret ;AN005;
1564 push ax ;AN005; Save error
1565 push dx ;AN005;
1566 mov dh,-1 ;AN005; Display FIND:
1567 mov ax,msg_find ;AN005;
1568 xor cx,cx ;AN007; ;AN005; No substitution text
1569 mov bx,STDERR ;AN005; Sent to STD OUT
1570 call display_msg ;AN005; Display the message
1571 pop dx ;AN005;
1572 pop ax ;AN005; Restore error
1573prt_ret:
1574 ret ;AN005;
1575prt_find endp ;AN005;
1576
1577
1578;------------------------------------
1579;-
1580;- Procedure name: display_and_die
1581;-
1582;- Purpose: Called when the parser finds that
1583;- required arguments were not entered
1584;- from the command line.
1585;-
1586;- INPUT: AX = Error number
1587;-
1588;------------------------------------
1589display_and_die proc near
1590 call prt_find ;AN005;
1591 xor cx,cx ;AN007; ;AN000; No substitution text
1592 mov cs:errlevel,ERRORLEVEL_TWO ;AC005; Error code for exit
1593
1594 mov bx,STDERR ;AN000; Sent to STD OUT
1595 call display_msg ;AN000; Display the message
1596 call terminate ;AN000; and Terminate
1597 ret ;AN000;
1598display_and_die endp
1599
1600;------------------------------------
1601;-
1602;- Procedure name: get_length
1603;-
1604;- Purpose: determine the length of a null
1605;- ending string.
1606;-
1607;- INPUT: ES:DI = string address
1608;- ES:BX = save address (0=no save)
1609;-
1610;- OUTPUT: AX = length of string
1611;------------------------------------
1612get_length proc near
1613 push di
1614 push bx
1615 push dx
1616 xor ax,ax ;init string length
1617look_str:
1618 mov dl,es:[di] ;get character
1619 or bx,bx ;save it?
1620 jz no_save
1621 mov es:[bx],dl ;save character
1622 inc bx ;save next character
1623no_save: ;AN007;
1624 and dl,dl ;AN007; ;check for eol (asciiz string)
1625 je done_look ;if so, exit
1626 cmp dl,0dh ;AN005; check for eol (carriage return)
1627 je done_look ;AN005;
1628 inc ax ;increment length
1629 inc di ;look at next character
1630 jmp look_str
1631done_look:
1632 pop dx
1633 pop bx
1634 pop di
1635 ret
1636get_length endp
1637
1638
1639
1640
1641;
1642;----- BUFFER AREA --------
1643st_length dw 0 ;String argument length
1644st_buffer db st_buf_size dup(?) ;String argument buffer
1645
1646file_name_len dw 0 ;File name length
1647file_name_buf dw 0 ;File name buffer offset
1648
1649buffer db buffer_size+2 dup(?) ;file data buffer
1650
1651include msgdcl.inc
1652
1653code ends
1654
1655;--------------------------
1656;--- STACK SEGMENT ---
1657;--------------------------
1658stack segment para stack 'STACK'
1659 dw (362 - 80h) +64 dup(?,?) ;(362 - 80h) == New - old IBM ROM
1660stack_top equ $
1661stack ends
1662
1663 end start
1664
diff --git a/v4.0/src/CMD/FIND/FIND.INC b/v4.0/src/CMD/FIND/FIND.INC
new file mode 100644
index 0000000..4434908
--- /dev/null
+++ b/v4.0/src/CMD/FIND/FIND.INC
@@ -0,0 +1,100 @@
1;;
2;; Long Conditional Jump Macros
3;;
4lja macro Farlabel
5 local Nearlabel
6 jna Nearlabel
7 jmp Farlabel
8Nearlabel:
9 endm
10ljae macro Farlabel
11 local Nearlabel
12 jnae Nearlabel
13 jmp Farlabel
14Nearlabel:
15 endm
16ljb macro Farlabel
17 local Nearlabel
18 jnb Nearlabel
19 jmp Farlabel
20Nearlabel:
21 endm
22ljc macro Farlabel
23 local Nearlabel
24 jnc Nearlabel
25 jmp Farlabel
26Nearlabel:
27 endm
28ljbe macro Farlabel
29 local Nearlabel
30 jnbe Nearlabel
31 jmp Farlabel
32Nearlabel:
33 endm
34lje macro Farlabel
35 local Nearlabel
36 jne Nearlabel
37 jmp Farlabel
38Nearlabel:
39 endm
40ljz macro Farlabel
41 local Nearlabel
42 jnz Nearlabel
43 jmp Farlabel
44Nearlabel:
45 endm
46ljg macro Farlabel
47 local Nearlabel
48 jng Nearlabel
49 jmp Farlabel
50Nearlabel:
51 endm
52ljge macro Farlabel
53 local Nearlabel
54 jnge Nearlabel
55 jmp Farlabel
56Nearlabel:
57 endm
58ljl macro Farlabel
59 local Nearlabel
60 jnl Nearlabel
61 jmp Farlabel
62Nearlabel:
63 endm
64ljle macro Farlabel
65 local Nearlabel
66 jnle Nearlabel
67 jmp Farlabel
68Nearlabel:
69 endm
70ljnc macro Farlabel
71 local Nearlabel
72 jc Nearlabel
73 jmp Farlabel
74Nearlabel:
75 endm
76ljne macro Farlabel
77 local Nearlabel
78 je Nearlabel
79 jmp Farlabel
80Nearlabel:
81 endm
82ljnz macro Farlabel
83 local Nearlabel
84 jz Nearlabel
85 jmp Farlabel
86Nearlabel:
87 endm
88ljno macro Farlabel
89 local Nearlabel
90 jo Nearlabel
91 jmp Farlabel
92Nearlabel:
93 endm
94ljo macro Farlabel
95 local Nearlabel
96 jno Nearlabel
97 jmp Farlabel
98Nearlabel:
99 endm
100 \ No newline at end of file
diff --git a/v4.0/src/CMD/FIND/FIND.LNK b/v4.0/src/CMD/FIND/FIND.LNK
new file mode 100644
index 0000000..a1fe82a
--- /dev/null
+++ b/v4.0/src/CMD/FIND/FIND.LNK
@@ -0,0 +1,4 @@
1FIND+
2FINDMES
3FIND.EXE;
4 \ No newline at end of file
diff --git a/v4.0/src/CMD/FIND/FIND.SKL b/v4.0/src/CMD/FIND/FIND.SKL
new file mode 100644
index 0000000..071c9d1
--- /dev/null
+++ b/v4.0/src/CMD/FIND/FIND.SKL
@@ -0,0 +1,12 @@
1:util FIND
2
3:class 1 ;Extended errors ;AN005;
4
5:class 2 ;Parser errors ;AN005;
6
7:class A ;Utility specific errors ;AN005;
8:use 1 COMMON1 ;AN005; ;"Incorrect DOS version"
9:use 2 EXTEND8 ;AN005; ;"Insufficient memory"
10:def 4 "FIND: " ;AN005;
11
12:end
diff --git a/v4.0/src/CMD/FIND/FINDMES.ASM b/v4.0/src/CMD/FIND/FINDMES.ASM
new file mode 100644
index 0000000..30713e2
--- /dev/null
+++ b/v4.0/src/CMD/FIND/FINDMES.ASM
@@ -0,0 +1,19 @@
1 title FIND Messages
2
3Message macro sym,text
4public sym,sym&_len
5sym db text
6sym&_len db $-sym
7endm
8
9CR equ 0dh ;A Carriage Return
10LF equ 0ah ;A Line Feed
11
12code segment public
13
14 PUBLIC heading
15 message heading,<CR,LF,"---------- ">
16
17code ends
18 end
19 \ No newline at end of file
diff --git a/v4.0/src/CMD/FIND/MAKEFILE b/v4.0/src/CMD/FIND/MAKEFILE
new file mode 100644
index 0000000..3bb43c1
--- /dev/null
+++ b/v4.0/src/CMD/FIND/MAKEFILE
@@ -0,0 +1,34 @@
1#************************** makefile for cmd\... ***************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7
8#
9####################### dependencies begin here. #########################
10#
11
12all: find.exe
13
14find.ctl: find.skl \
15 $(msg)\$(COUNTRY).msg \
16 makefile
17
18find.obj: find.asm \
19 makefile \
20 find.ctl \
21 find.cla \
22 find.cl1 \
23 find.cl2 \
24 find.inc \
25 $(inc)\parse.asm \
26 $(inc)\psdata.inc \
27 $(inc)\syscall.inc \
28 $(inc)\msgserv.asm \
29 $(inc)\sysmsg.inc
30
31findmes.obj: findmes.asm
32
33find.exe: find.obj findmes.obj
34 link find+findmes,find.exe/ex;