]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/FIND/FIND.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / CMD / FIND / FIND.ASM
1 title DOS FIND Utility
2 ;\ f \e0
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 ;--------------------------
108 BREAK MACRO subtitle
109 SUBTTL subtitle
110 PAGE
111 ENDM
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
126 MSG_UTILNAME <FIND> ;AN000;
127
128 ;--------------------------
129 ;- EQUATES
130 ;--------------------------
131 FALSE equ 0
132 TRUE equ NOT FALSE
133
134 CR equ 0dh ;A Carriage Return
135 LF equ 0ah ;A Line Feed
136 quote_char equ 22h ;A double quote character
137
138
139 buffer_size equ 4096 ;file buffer size
140 st_buf_size equ 128 ;string arg. buffer size
141 fname_buf_size equ 64 ;file name buffer size
142
143
144 ;----- DOS EQUATES -----;
145 STDIN equ 0 ;AN000; Handle
146 STDOUT equ 1 ;AN000; Handle
147 STDERR equ 2 ;AN000; Handle
148
149 GetCPSW equ 03303h ;AN000; Int 021h function call
150 GetExtAttr equ 05702h ;AN000; Int 021h function call
151 SetExtAttr equ 05704h ;AN000; Int 021h function call
152
153 ERROR_ACCESS_DENIED equ 5 ;AN000; Int 021h error return
154
155 CPSWActive equ 1 ;AN000; Indicates Code Page support is active
156 CPSWNotActive equ 0 ;AN000; Just the opposite
157
158 ERRORLEVEL_ZERO equ 0 ;AN000; Termination error level
159 ERRORLEVEL_ONE equ 1 ;AN000; Termination error level
160 ERRORLEVEL_TWO equ 2 ;AN000; Termination error level
161
162 ;------------------------
163 ;- MESSAGE EQUATES
164 ;------------------------
165
166 msg_file_not_found equ 2 ;AN000; File not found %s
167 msg_access_denied equ 5 ;AN000; Access denied %s
168 msg_read_error equ 30 ;AN000; Read error in %s
169 msg_inv_num_parm equ 2 ;AN000; Invalid number of parameters
170 msg_inv_parm equ 10 ;AN000; Invalid Parameter %s
171 msg_required_missing equ 2 ;AN005; Required parameter missing
172 msg_find equ 4 ;AN000; FIND:
173 msg_code_page_mismatch equ 37 ;AN005; Code Page mismatch
174 msg_switch equ 3 ;AN005; Invalid switch
175
176 ;-----------------------
177 ;-- Parser equates
178 ;-----------------------
179
180 FarSW equ 0 ;AN000;
181 DateSW equ 0 ;AN000;
182 TimeSW equ 0 ;AN000;
183 FileSW equ 1 ;AN000;
184 CAPSW equ 1 ;AN000;
185 CmpxSW equ 0 ;AN000;
186 DrvSW equ 0 ;AN000;
187 QusSW equ 1 ;AN000;
188 NumSW equ 0 ;AN000;
189 KeySW equ 0 ;AN000;
190 SwSW equ 1 ;AN000;
191 Val1SW equ 0 ;AN000;
192 Val2SW equ 0 ;AN000;
193 Val3SW equ 0 ;AN000;
194
195 ;------------------------
196 ; SUBLIST Equates
197 ;------------------------
198 Left_Align equ 0 ;AN000; 00xxxxxx
199 Right_Align equ 80h ;AN000; 10xxxxxx
200
201 Char_Field_Char equ 0 ;AN000; a0000000
202 Char_Field_ASCIIZ equ 10h ;AN000; a0010000
203
204 Unsgn_Bin_Byte equ 11h ;AN000; a0010001 - Unsigned Binary to Decimal character
205 Unsgn_Bin_Word equ 21h ;AN000; a0100001
206 Unsgn_Bin_DWord equ 31h ;AN000; a0110001
207
208 Sgn_Bin_Byte equ 12h ;AN000; a0010010 - Signed Binary to Decimal character
209 Sgn_Bin_Word equ 22h ;AN000; a0100010
210 Sgn_Bin_DWord equ 32h ;AN000; a0110010
211
212 Bin_Hex_Byte equ 13h ;AN000; a0010011 - Unsigned Binary to Hexidecimal character
213 Bin_Hex_Word equ 23h ;AN000; a0100011
214 Bin_Hex_DWord equ 33h ;AN000; a0110011
215
216 ;------------------------------
217 ; EXTENDED ATTRIBUTE Equates
218 ;------------------------------
219 File_Type_None equ 00000000b ;AN001; unspecified file type
220 File_Type_Text equ 00100000b ;AN001; ASCII text file
221 File_Type_Rtl equ 00100001b ;AN001; ASCII text file in RTL
222
223 EAISBINARY equ 02h ;AN001; ea_type
224 EASYSTEM equ 8000h ;AN001; ea_flags
225
226 ;---------------------------------------
227 ;-------------- CODE SEGMENT -----------
228 ;---------------------------------------
229
230 code segment public
231 assume cs:code
232 assume ds:nothing
233 assume es:nothing
234 assume ss:stack
235
236 jmp start
237
238 ;\f
239 ;--------------------
240 .xlist
241 .xcref
242 INCLUDE parse.asm
243 .list
244 .cref
245 ;--------------------
246
247 EXTRN heading:byte,heading_len:byte
248
249 ;*********************************
250 ;* Extended Attribute Structures *
251 ;*********************************
252 querylist struc ;AN001; ;query general list
253 qea_num dw 1 ;AN001;
254 qea_type db EAISBINARY ;AN001;
255 qea_flags dw EASYSTEM ;AN001;
256 qea_namelen db ? ;AN001;
257 qea_name db " " ;AN001;
258 querylist ends ;AN001;
259
260 cp_qlist querylist <1,EAISBINARY,EASYSTEM,2,"CP"> ;AN001; ;query code page attr.
261
262 cp_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
270 cp dw ? ;AN001; ; ea value (code page)
271 cp_len equ ($ - cp_list) ;AN001;
272
273 ;-------Save area for Code Pages
274 src_cp dw ? ;AN000; Save area for source code page
275 tgt_cp dw ? ;AN000; Save area for target code page
276 str_cp dw ? ;AN005; Save area for search string code page
277
278
279
280 ;-----------------------
281 ;----- Misc Data ------
282 bufferDB db 6 dup(0) ;AN006;
283 dbcs_off dw 0 ;AN006;
284 dbcs_seg dw 0 ;AN006;
285 dbcs_len dw 0 ;AN006;
286
287 ccolon db ": "
288 n1_buf db "["
289 n2_buf db 8 dup(0) ;buffer for number conversion
290
291 errlevel 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
300 opt_tbl:
301
302 v_flag db FALSE ;AN000; Set to FALSE
303 c_flag db FALSE ;AN000; Set to FALSE
304 n_flag db FALSE ;AN000; Set to FALSE
305
306
307 ;----- LINE COUNTERS
308 mtch_cntr dw 0 ;matched lines counter
309 line_cntr dw 0 ;line counter
310
311 ;-------------------------------------------
312 ;- MESSAGE RETRIEVER SUBSTITUTION LIST
313 ;-------------------------------------------
314
315 MSG_SERVICES <MSGDATA> ;AN000;
316
317 sublist label dword ;AN000;
318 sl_size db 11 ;AN000; SUBLIST Size, in bytes
319 sl_res db 0 ;AN000; reserved
320 sl_ptr_o dw ? ;AN000; Offset PTR to data item
321 sl_ptr_s dw ? ;AN000; Segment PTR to data item
322 sl_n db 0 ;AN000; n of %n
323 sl_flag db ? ;AN000; Data-Type flags
324 sl_maxw db 0 ;AN000; Max width
325 sl_minw db 0 ;AN000; Min width
326 sl_pad db ' ' ;AN000; Pad character
327
328
329 parm db ? ;AN000; Save area for invalid parm
330 cpsw_state db CPSWNotActive ;AN000; Save area indicating state of Code Page Support
331
332 ;******************************************************************************
333 ;* PARSER DATA STRUCTURES FOLLOW
334 ;******************************************************************************
335
336 parms 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
342 parms1 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 ;------------------------------
351 parmsx 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
359 parmsx1 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 ;------------------------------
368 pos1 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 ;------------------------------
378 pos2 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 ;------------------------------
389 sw1 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
395 n_swch db "/N",0 ;AN000;
396 v_swch db "/V",0 ;AN000;
397 c_swch db "/C",0 ;AN000;
398
399
400 ;------------------------------
401 ;- VALUE LIST DEFINITION FOR NO VALUES
402 ;------------------------------
403 novals label word ;AN000;
404 db 0 ;AN000; VALUE LIST
405
406
407 ;------------------------------
408 ;- RETURN BUFFER FOR POSITIONAL PARAMETERS
409 ;------------------------------
410 ret_buff label word ;AN000;
411 rb_type db ? ;AN000; TYPE RETURNED
412 rb_item_tag db ? ;AN000; SPACE FOR ITEM TAG
413 rb_synonym dw ? ;AN000; ES:rb_synonym points to synonym
414 rb_value_lo dw ? ;AN000; SPACE FOR VALUE
415 rb_value_hi dw ? ;AN000; SPACE FOR VALUE
416
417
418
419
420 did_file db FALSE ;AN004; if true then already processed a file
421 got_eol db FALSE ;AN004; if false then possibly more filenames on command line
422 got_filename db FALSE ;AN004; if true then parser found a filename on command line
423 got_srch_str db FALSE ;AN000; if true then parser found search string on command line
424 ordinal dw 0 ;AN000; parser ordinal
425 crlf db CR,LF ;AN000;
426
427
428 ;\f
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
474 START:
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 ;-----------------------------------
493 Set_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
511 p_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;
520 PARSER:
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 ;---------------------
546 save_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 ;---------------------
570 open_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
577 o_cont: ;AN004;
578 mov dx,cs:file_name_buf ;AC000;addrss. of the file name
579 openit:
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
585 cp_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!
601 c_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
607 cp_match:
608 pop ax ;AN000; Restore handle
609 ;---------------------
610 ;- PRINT FILE NAME
611 ;---------------------
612 say_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
631 xx1:
632 pop ax
633
634 ;---------------------
635 ;- Fill Buffer for Matching
636 ;---------------------
637 fill:
638 mov bx,ax ;retrieve handle
639 refill:
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
646 no_read_error:
647 or ax,ax ;if ax=0 then all done
648 jnz Truncate
649 DoNullRead:
650 cmp cs:c_flag,TRUE ;count only flag set?
651 jne sj2
652 call print_count
653 sj2:
654 and bx,bx ;Using STD IN?
655 jnz regular
656 jmp foo ;if so: all done, exit
657 regular:
658 mov ah,close ;otherwise close the file
659 int 021h
660 jmp scan_rest ;get another file
661
662 do_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 ;---------------------------
668 Truncate:
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
686 chop:
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
707 go_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
730 last_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
739 no_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
746 more_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 ;---------------------------
762 try_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
780 NO_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
784 another_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
793 lop:
794 pop dx
795 push dx
796 inc dx ;different algorithm!
797 mov si,offset st_buffer ;pointer to beg. of string argument
798
799 comp_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
812 nopre:
813 lodsb
814 cmp al,byte ptr [di]
815 jz kmatch
816 back_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
834 try_again_opt1:
835 pop dx
836 jmp short try_again_opt ;AN007;
837
838
839 kmatch1:
840 dec dx ;last char had prefix so it was
841 ; long.
842 kmatch:
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
849 a_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 ;---------------------------
858 try_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
872 prt_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
878 no_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
883 no_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
903 more_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
914 no_seek:
915 jmp refill ;no errors: refill the buffer
916 read_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 ;---------------------
930 open_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
937 DoNorm: ;AN000;
938 mov ax,msg_file_not_found ;AN000; Message for File Not Found
939
940 r_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 ;---------------------
955 scan_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
963 foo:
964 mov cs:errlevel,ERRORLEVEL_ZERO ;AN000; Proper code
965 call terminate ;AN000; reset codepage and terminate
966
967
968 ;--------------------------
969 ; Clear Counters
970 ;--------------------------
971 clr_cntrs proc near
972 mov byte ptr cs:mtch_cntr,0
973 mov byte ptr cs:line_cntr,0
974 ret
975 clr_cntrs endp
976
977
978 ;--------------------------
979 ; Print Count of Matched lines
980 ; Modifies: AX,CX,DX and DI
981 ;--------------------------
982 print_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
990 sj3:
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
1001 print_count endp
1002
1003 ;--------------------------
1004 ; Print relative line number
1005
1006 ; Modifies: AX,CX and DI
1007 ;--------------------------
1008 prt_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
1022 prt_lcntr endp
1023
1024 ;--------------------------
1025 ; Print string to STDOUT
1026 ;--------------------------
1027 prout proc near
1028 mov bx,STDOUT
1029 mov ah,write
1030 int 021h
1031 ret
1032 prout 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 ;--------------------------
1046 bin2asc proc near
1047 mov bx,0ah
1048 xor cx,cx
1049 go_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
1059 div_done:
1060 add al,'0'
1061 push ax
1062 mov bx,cx
1063 deposit:
1064 pop ax
1065 stosb
1066 loop deposit
1067 mov cx,bx
1068 ret
1069 bin2asc 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 ;--------------------------
1100 next_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
1107 no_p:
1108 inc di
1109 dec cx
1110 clc
1111 ret
1112
1113 no_kleft:
1114 stc
1115 ret
1116 next_kchar endp
1117
1118 ;--------------------------
1119 ; Get DOS dbcs table vector
1120 ; entry: none
1121 ; exit: none
1122 ; modifies: none
1123 ;--------------------------
1124 get_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;
1164 get_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 ;--------------------------
1173 is_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
1187 is_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
1197 is_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
1202 is_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
1206 is_again:
1207 add si,2 ;no, increment ptr to next range
1208 jmp is_loop
1209
1210 is_found:
1211 stc ;byte is lead byte of db char, set carry
1212
1213 is_exit:
1214 pop ax
1215 pop si
1216 pop es
1217 ;
1218 ret
1219 is_prefix endp
1220
1221
1222 ;\f
1223 ;---------------------
1224 ;- Terminate process
1225 ;---------------------
1226 terminate 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
1231 terminate endp ;AN000;
1232
1233 ;\f
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 ;************************************************************
1249 set_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
1254 set_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 ;************************************************************
1273 get_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
1287 get_cp endp ;AN000;
1288
1289
1290 ;\f
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 ;************************************************************
1321 display_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
1340 disp_done: ;AN000;
1341 pop ds ;AN000; Restore DS
1342 ret ;AN000;
1343 display_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 ;************************************************************
1372 EOL equ -1 ;AN000; Indicator for End-Of-Line
1373 NOERROR equ 0 ;AN000; Return Indicator for No Errors
1374 SYNTAX equ 9 ;AN000; Syntax error from parser
1375
1376 SWITCH equ 3 ;AN000;
1377 FILESPEC equ 5 ;AN000;
1378 QUOTED_STRING equ 9 ;AN000;
1379
1380 parse proc near ;AN000;
1381 ;--------------------------------------
1382 ; address of command line in DS:SI
1383 ;--------------------------------------
1384 ;------------------------------------------
1385 ;- Look for the search string and switches
1386 ;------------------------------------------
1387 parse_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
1397 p_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;
1403 CONT2: ;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
1411 cont3:
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 ;-----------------------------
1421 its_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
1427 its_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 ;-----------------------------
1438 its_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
1443 chek_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
1447 chek_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
1451 whoops: ;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
1456 end_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
1462 rett: ;AN000;
1463 ret ;AN000;
1464
1465 doexit:
1466 mov cs:errlevel,ERRORLEVEL_ZERO;AN000; Proper code
1467 call terminate ;AN000; reset codepage and terminate
1468
1469 parse 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 ;------------------------------------
1483 pre_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 ;
1493 pp_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
1507 pp_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
1520 pp_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
1525 pp_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
1531 pp_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
1536 pp_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;
1547 pre_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 ;------------------------------------
1561 prt_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
1573 prt_ret:
1574 ret ;AN005;
1575 prt_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 ;------------------------------------
1589 display_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;
1598 display_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 ;------------------------------------
1612 get_length proc near
1613 push di
1614 push bx
1615 push dx
1616 xor ax,ax ;init string length
1617 look_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
1623 no_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
1631 done_look:
1632 pop dx
1633 pop bx
1634 pop di
1635 ret
1636 get_length endp
1637
1638
1639
1640
1641 ;\f
1642 ;----- BUFFER AREA --------
1643 st_length dw 0 ;String argument length
1644 st_buffer db st_buf_size dup(?) ;String argument buffer
1645
1646 file_name_len dw 0 ;File name length
1647 file_name_buf dw 0 ;File name buffer offset
1648
1649 buffer db buffer_size+2 dup(?) ;file data buffer
1650
1651 include msgdcl.inc
1652
1653 code ends
1654
1655 ;--------------------------
1656 ;--- STACK SEGMENT ---
1657 ;--------------------------
1658 stack segment para stack 'STACK'
1659 dw (362 - 80h) +64 dup(?,?) ;(362 - 80h) == New - old IBM ROM
1660 stack_top equ $
1661 stack ends
1662
1663 end start
1664