From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/FIND/FIND.ASM | 1664 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1664 insertions(+) create mode 100644 v4.0/src/CMD/FIND/FIND.ASM (limited to 'v4.0/src/CMD/FIND/FIND.ASM') 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 @@ + title DOS FIND Utility +; 0 +;******************************************************************** +;* +;* UTILITY NAME: find.exe +;* +;* SOURCE FILE NAME: find.asm +;* +;* STATUS: Find utility, DOS Version 4.0 +;* +;* SYNTAX (Command line) +;* +;* FIND [/V][/C][/N] "string" [[d:][path]filename[.ext]...] +;* +;* where: +;* +;* /V - Display all lines NOT containing the string +;* /C - Display only a count of lines containing string +;* /N - Display number of line containing string +;* +;* +;* UTILITY FUNCTION: +;* +;* Searches the specified file(s) looking for the string the user +;* entered from the command line. If file name(s) are specifeied, +;* those names are displayed, and if the string is found, then the +;* entire line containing that string will be displayed. Optional +;* parameters modify that behavior and are described above. String +;* arguments have to be enclosed in double quotes. (Two double quotes +;* if a double quote is to be included). Only one string argument is +;* presently allowed. The maximum line size is determined by buffer +;* size. Bigger lines will bomb the program. If no file name is given +;* then it will asssume the input is coming from the standard Input. +;* No errors are reported when reading from standard Input. +;* +;* +;* EXIT: +;* The program returns errorlevel: +;* 0 - OK, and some matches +;* 1 - +;* 2 - Some Error +;* +;* +;* Revision History: +;* +;* V1.1 8/23/82 M.A.U. (Microsoft) +;* +;* V1.2 9/22/82 M.A.U. (Microsoft) +;* Added the -c and -n options +;* +;* 9/23/82 M.A.U. (Microsoft) +;* Added DOS version number control +;* +;* 10/07/82 Rev.2 M.A.U. (Microsoft) +;* Changed quote for double quotes, and added +;* file name printing +;* +;* 10/20/82 Rev.3 M.A.U. (Microsoft) +;* Modified IBM name to FIND, and changed the text +;* of some messages. +;* +;* 10/25/82 Rev.4 M.A.U. (Microsoft) +;* Changed name to FIND and all messages to the +;* IBM form. +;* +;* 10/27/82 Rev.5 M.A.U. (Microsoft) +;* Made the correct exit on version check in case +;* of a 1.x DOS. +;* +;* 11/4/82 Rev. 5 A.R. Reynolds (Microsoft) +;* Messages moved to external module +;* +;* 11/10/82 Rev. 6 M.A. U. (Microsoft) +;* Corrected problem with line numbers, and a problem +;* with seeking for 0 chars. +;* +;* 03/30/83 Rev. 7 M.A. U. (Microsoft) +;* Added patch area for bug fixing. +;* +;* 04/14/83 Rev. 8 M.A. U. (Microsoft) +;* Made changes for Kanji characters. (ugh!) +;* +;* 12/17/84 Rev. 9 Zibo (Microsoft) +;* Fix boundary case for buffer containing exact line +;* +;* V4.0 : 6/29/87 Russ W (IBM) +;* Lines commented with ;AN000; +;* Add support for IBM Parse service routines +;* Add support for IBM Message Retriever Service Routines +;* Add support for Code Page File Tags +;* Made PROCs out of all labels that were targets of a call (not commented with AN000) +;* Removed patch area for "bug fixing" +;* +;* V4.0 : 9/15/87 Bill L, (IBM) +;* ;AN001; = DCR 201, changes to extended attributes support +;* ;AN002; = PTM 1090 +;* ;AN003; = DCR 191 +;* ;AN004; = PTM 1630 +;* ;AN005; = PTM 1643, PTM 1675, PTM 1754 +;* ;AN006; = DBCS support +;* ;AN007; = Optimizations to save disk space on ship diskettes +;* +;********************************************************************** + +;-------------------------- +;- MACRO DEFINITIONS +;-------------------------- +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM + + +;---------------------------; +;- INCLUDE FILES ; +;---------------------------; +.xlist ; +.xcref ; + INCLUDE SYSCALL.INC ; + INCLUDE sysmsg.inc ; ;AN000; Include message equates and MACROS + INCLUDE find.inc ; ;AN000; Include find equates and MACROS +.list ; +.cref ; +;---------------------------; + +MSG_UTILNAME ;AN000; + +;-------------------------- +;- EQUATES +;-------------------------- +FALSE equ 0 +TRUE equ NOT FALSE + +CR equ 0dh ;A Carriage Return +LF equ 0ah ;A Line Feed +quote_char equ 22h ;A double quote character + + +buffer_size equ 4096 ;file buffer size +st_buf_size equ 128 ;string arg. buffer size +fname_buf_size equ 64 ;file name buffer size + + +;----- DOS EQUATES -----; +STDIN equ 0 ;AN000; Handle +STDOUT equ 1 ;AN000; Handle +STDERR equ 2 ;AN000; Handle + +GetCPSW equ 03303h ;AN000; Int 021h function call +GetExtAttr equ 05702h ;AN000; Int 021h function call +SetExtAttr equ 05704h ;AN000; Int 021h function call + +ERROR_ACCESS_DENIED equ 5 ;AN000; Int 021h error return + +CPSWActive equ 1 ;AN000; Indicates Code Page support is active +CPSWNotActive equ 0 ;AN000; Just the opposite + +ERRORLEVEL_ZERO equ 0 ;AN000; Termination error level +ERRORLEVEL_ONE equ 1 ;AN000; Termination error level +ERRORLEVEL_TWO equ 2 ;AN000; Termination error level + +;------------------------ +;- MESSAGE EQUATES +;------------------------ + +msg_file_not_found equ 2 ;AN000; File not found %s +msg_access_denied equ 5 ;AN000; Access denied %s +msg_read_error equ 30 ;AN000; Read error in %s +msg_inv_num_parm equ 2 ;AN000; Invalid number of parameters +msg_inv_parm equ 10 ;AN000; Invalid Parameter %s +msg_required_missing equ 2 ;AN005; Required parameter missing +msg_find equ 4 ;AN000; FIND: +msg_code_page_mismatch equ 37 ;AN005; Code Page mismatch +msg_switch equ 3 ;AN005; Invalid switch + +;----------------------- +;-- Parser equates +;----------------------- + +FarSW equ 0 ;AN000; +DateSW equ 0 ;AN000; +TimeSW equ 0 ;AN000; +FileSW equ 1 ;AN000; +CAPSW equ 1 ;AN000; +CmpxSW equ 0 ;AN000; +DrvSW equ 0 ;AN000; +QusSW equ 1 ;AN000; +NumSW equ 0 ;AN000; +KeySW equ 0 ;AN000; +SwSW equ 1 ;AN000; +Val1SW equ 0 ;AN000; +Val2SW equ 0 ;AN000; +Val3SW equ 0 ;AN000; + +;------------------------ +; SUBLIST Equates +;------------------------ +Left_Align equ 0 ;AN000; 00xxxxxx +Right_Align equ 80h ;AN000; 10xxxxxx + +Char_Field_Char equ 0 ;AN000; a0000000 +Char_Field_ASCIIZ equ 10h ;AN000; a0010000 + +Unsgn_Bin_Byte equ 11h ;AN000; a0010001 - Unsigned Binary to Decimal character +Unsgn_Bin_Word equ 21h ;AN000; a0100001 +Unsgn_Bin_DWord equ 31h ;AN000; a0110001 + +Sgn_Bin_Byte equ 12h ;AN000; a0010010 - Signed Binary to Decimal character +Sgn_Bin_Word equ 22h ;AN000; a0100010 +Sgn_Bin_DWord equ 32h ;AN000; a0110010 + +Bin_Hex_Byte equ 13h ;AN000; a0010011 - Unsigned Binary to Hexidecimal character +Bin_Hex_Word equ 23h ;AN000; a0100011 +Bin_Hex_DWord equ 33h ;AN000; a0110011 + +;------------------------------ +; EXTENDED ATTRIBUTE Equates +;------------------------------ +File_Type_None equ 00000000b ;AN001; unspecified file type +File_Type_Text equ 00100000b ;AN001; ASCII text file +File_Type_Rtl equ 00100001b ;AN001; ASCII text file in RTL + +EAISBINARY equ 02h ;AN001; ea_type +EASYSTEM equ 8000h ;AN001; ea_flags + +;--------------------------------------- +;-------------- CODE SEGMENT ----------- +;--------------------------------------- + +code segment public + assume cs:code + assume ds:nothing + assume es:nothing + assume ss:stack + + jmp start + +; +;-------------------- +.xlist +.xcref +INCLUDE parse.asm +.list +.cref +;-------------------- + + EXTRN heading:byte,heading_len:byte + +;********************************* +;* Extended Attribute Structures * +;********************************* +querylist struc ;AN001; ;query general list +qea_num dw 1 ;AN001; +qea_type db EAISBINARY ;AN001; +qea_flags dw EASYSTEM ;AN001; +qea_namelen db ? ;AN001; +qea_name db " " ;AN001; +querylist ends ;AN001; + +cp_qlist querylist <1,EAISBINARY,EASYSTEM,2,"CP"> ;AN001; ;query code page attr. + +cp_list label word ;AN001; ;code page attr. get/set list + dw 1 ;AN001; ; # of list entries + db EAISBINARY ;AN001; ; ea type + dw EASYSTEM ;AN001; ; ea flags + db ? ;AN001; ; ea return code + db 2 ;AN001; ; ea name length + dw 2 ;AN001; ; ea value length + db "CP" ;AN001; ; ea name +cp dw ? ;AN001; ; ea value (code page) +cp_len equ ($ - cp_list) ;AN001; + +;-------Save area for Code Pages +src_cp dw ? ;AN000; Save area for source code page +tgt_cp dw ? ;AN000; Save area for target code page +str_cp dw ? ;AN005; Save area for search string code page + + + +;----------------------- +;----- Misc Data ------ +bufferDB db 6 dup(0) ;AN006; +dbcs_off dw 0 ;AN006; +dbcs_seg dw 0 ;AN006; +dbcs_len dw 0 ;AN006; + +ccolon db ": " +n1_buf db "[" +n2_buf db 8 dup(0) ;buffer for number conversion + +errlevel db ERRORLEVEL_ZERO ;AN000; Errrorlevel save area + +;----- OPTION FLAGS ---- +; If a flag is set (0ffh) then the option has been selected, if +;reset (0) then it has been not. All options are reset initially. +; NOTE: the order of this table has to remain consistent with the +;options dispatch code. If any changes are made they have to +;correspond with the code. + +opt_tbl: + +v_flag db FALSE ;AN000; Set to FALSE +c_flag db FALSE ;AN000; Set to FALSE +n_flag db FALSE ;AN000; Set to FALSE + + +;----- LINE COUNTERS +mtch_cntr dw 0 ;matched lines counter +line_cntr dw 0 ;line counter + +;------------------------------------------- +;- MESSAGE RETRIEVER SUBSTITUTION LIST +;------------------------------------------- + +MSG_SERVICES ;AN000; + +sublist label dword ;AN000; +sl_size db 11 ;AN000; SUBLIST Size, in bytes +sl_res db 0 ;AN000; reserved +sl_ptr_o dw ? ;AN000; Offset PTR to data item +sl_ptr_s dw ? ;AN000; Segment PTR to data item +sl_n db 0 ;AN000; n of %n +sl_flag db ? ;AN000; Data-Type flags +sl_maxw db 0 ;AN000; Max width +sl_minw db 0 ;AN000; Min width +sl_pad db ' ' ;AN000; Pad character + + +parm db ? ;AN000; Save area for invalid parm +cpsw_state db CPSWNotActive ;AN000; Save area indicating state of Code Page Support + +;****************************************************************************** +;* PARSER DATA STRUCTURES FOLLOW +;****************************************************************************** + +parms label byte ;AN000; + dw parmsx ;AN000; POINTER TO PARMS STRUCURE + db 1 ;AN000; DELIMITER LIST FOLLOWS + db 1 ;AN000; NUMBER OF ADDITIONAL DELIMITERS + db ";" ;AN000; ADDITIONAL DELIMITER + +parms1 label byte ;AN005; + dw parmsx1 ;AN005; POINTER TO PARMS STRUCURE + db 1 ;AN005; DELIMITER LIST FOLLOWS + db 1 ;AN005; NUMBER OF ADDITIONAL DELIMITERS + db ";" ;AN005; ADDITIONAL DELIMITER + +;------------------------------ +;- STRUCTURE TO DEFINE FIND SYNTAX REQUIREMENTS +;------------------------------ +parmsx label word ;AN000; + db 1,2 ;AN000; THERE ARE BETWEEN 1 AND 2 POSITIONAL PARMS + dw pos1 ;AN000; POINTER TO POSITIONAL DEFINITION AREA + dw pos2 ;AN000; POINTER TO POSITIONAL DEFINITION AREA + db 1 ;AN000; THERE IS 1 SWITCH DEF AREA FOR "/V, /C, AND /N" + dw sw1 ;AN000; POINTER TO FIRST SWITCH DEFINITION AREA + dw 0 ;AN000; THERE ARE NO KEYWORDS IN FIND SYNTAX + +parmsx1 label word ;AN005; + db 0,0 ;AN005; THERE ARE BETWEEN 1 AND 2 POSITIONAL PARMS + db 1 ;AN005; THERE IS 1 SWITCH DEF AREA FOR "/V, /C, AND /N" + dw sw1 ;AN005; POINTER TO FIRST SWITCH DEFINITION AREA + dw 0 ;AN005; THERE ARE NO KEYWORDS IN FIND SYNTAX + + ;------------------------------ + ;- STRUCTURE TO DEFINE POSITIONAL PARM + ;------------------------------ +pos1 label word ;AN000; + dw 0080h ;AN000; QUOTED STRING, REQUIRED + dw 0000h ;AN000; NO CAPITALIZE + dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF + dw novals ;AN000; NO VALUE LIST + db 0 ;AN000; NO KEYWORDS + + ;------------------------------ + ;- STRUCTURE TO DEFINE POSITIONAL PARM + ;------------------------------ +pos2 label word ;AN000; + dw 0203h ;AN000; FILE NAME, OPTIONAL, REPEATS ALLOWED + dw 0001h ;AN000; CAPITALIZE BY FILE TABLE + dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF + dw novals ;AN000; NO VALUE LIST + db 0 ;AN000; NO KEYWORDS + + + ;------------------------------ + ;- STRUCTURE TO DEFINE THE SWITCHES + ;------------------------------ +sw1 label word ;AN000; + dw 0 ;AN000; NO MATCH FLAGS + dw 2 ;AN005; capitalize + dw ret_buff ;AN000; PLACE RESULT IN RET_BUFF + dw novals ;AN000; NO VALUE LIST + db 3 ;AN000; THREE SWITCHES IN FOLLOWING LIST +n_swch db "/N",0 ;AN000; +v_swch db "/V",0 ;AN000; +c_swch db "/C",0 ;AN000; + + + ;------------------------------ + ;- VALUE LIST DEFINITION FOR NO VALUES + ;------------------------------ +novals label word ;AN000; + db 0 ;AN000; VALUE LIST + + + ;------------------------------ + ;- RETURN BUFFER FOR POSITIONAL PARAMETERS + ;------------------------------ +ret_buff label word ;AN000; +rb_type db ? ;AN000; TYPE RETURNED +rb_item_tag db ? ;AN000; SPACE FOR ITEM TAG +rb_synonym dw ? ;AN000; ES:rb_synonym points to synonym +rb_value_lo dw ? ;AN000; SPACE FOR VALUE +rb_value_hi dw ? ;AN000; SPACE FOR VALUE + + + + +did_file db FALSE ;AN004; if true then already processed a file +got_eol db FALSE ;AN004; if false then possibly more filenames on command line +got_filename db FALSE ;AN004; if true then parser found a filename on command line +got_srch_str db FALSE ;AN000; if true then parser found search string on command line +ordinal dw 0 ;AN000; parser ordinal +crlf db CR,LF ;AN000; + + +; +;************************************************************ +;* +;* SUBROUTINE NAME: main +;* +;* SUBROUTINE FUNCTION: +;* Process the command line. If there are no errors, then open +;* the specified files, search for string, display it to the +;* standard output device. +;* +;* INPUT: Command line (described in program header) +;* +;* OUTPUT: +;* Files will be opened and read in. Regardless of the command +;* line parameters entered by the user, output will be written +;* to the standard output device handle 1. +;* +;* NORMAL EXIT: +;* File(s) opened (if not STDIN), read successfully, and closed. +;* Display requested information. +;* +;* ERROR CONDITIONS: +;* Incorrect DOS version +;* Invalid number of parameters +;* Syntax error +;* Access denied +;* File not found +;* Invalid Parameter +;* Read error in +;* +;* INTERNAL REFERENCES: +;* bin2asc +;* clr_cntrs +;* is_prefix +;* next_kchar +;* print_count +;* prout +;* prt_err +;* prt_err_2 +;* prt_file_name +;* prt_lcntr +;* +;************************************************************************** + + MSG_SERVICES ;AN000; + MSG_SERVICES ;AN003; Make retriever services available +START: + + mov ax,cs ;load ES to the right area, + mov es,ax ; + mov ds,ax ; + + call sysloadmsg ;AN000; Preload messages, Check DOS Version. + jnc Set_for_parse ;AN000; If no error, parse command line + + call prt_find ;AN005; + call sysdispmsg ;AN005; + + mov ah,Exit ;AN000; Terminate new way + mov al,0 ;AN000; Errorlevel 0 (Compatible!) + int 021h ;AN000; Bye bye! + +;----------------------------------- +;- DOS version is ok. Parse cmd line +;----------------------------------- +Set_for_parse: + call get_dbcs_vector ;AN006; ;Get DOS dbcs table vector +; + mov ah,GetCurrentPSP ;AN000; Get PSP address, returned in BX + int 021h ;AN000; + mov ds,bx ;AN000; Put PSP Seg in DS + mov si,081h ;AN000; Offset of command line in PSP + xor cx,cx ;AN000; Number of args processed so far = 0 + mov cs:ordinal,cx ;AN000; init parser ordinal + +;-------------------------------------- +; See if there was nothing entered +;-------------------------------------- + cmp byte ptr ds:080h,0 ;AN000; Check length of command line, + jne p_parse ;AN005; Go process the parameters + mov ax,msg_inv_num_parm ;AN000; No parms, too bad! + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Tell the unfortunate user +p_parse: + mov cs:got_filename,FALSE ;AN004; input file default is STDIN + + push cs ;A0005; ensure es is correct + pop es ;AN005; + + call clr_cntrs ;AN005; set all counters to zero + mov cx,cs:ordinal ;AN005; init parser ordinal + call pre_parse ;AN005; +PARSER: + push cs ;A0000; ensure es is correct + pop es + + call clr_cntrs ; set all counters to zero + mov cx,cs:ordinal ;AN000; init parser ordinal + call parse ;AN000; Parse command line + + push si ;AN000; Save ptr to remaining command line + push ds + + push cs ;Load new DS with CS + pop ds + mov cs:ordinal,cx ;AN000; Save parser ordinal + +;--------------------- +; get filespec size +;--------------------- + mov cs:file_name_buf,di ;save buffer offset from parser + xor bx,bx ;AN000;indicate no save again + call get_length ;AN000;get filespec length + mov es:file_name_len,ax ;save the name length + +;--------------------- +;- Check current state of CPSW +;--------------------- +save_src_cp: + mov ax,GetCPSW ;AN000; Get CPSW state, assume support is OFF + int 021h ;AN000; DL: 0=NotSupported,1=Supported + jc open_read ;AN000; If error, assume CPSW inactive + mov cs:cpsw_state,dl ;AN000; Save current state + and dl,dl ;AN007; ;AN000; If inactive, (same as CMP dl,0) + je open_read ;AN000; do nothing + +;-------Code Page Switching is loaded and active! +;-------Save codepage of target handle ---------- + mov bx,STDOUT ;AN000; For Standard output device + call get_cp ;AN000; Get the current codepage + jc open_read ;AN000; Error condition + mov ax,cs:cp ;AN000; Save target code page + mov cs:tgt_cp,ax ;AN000; for later reference + xor bx,bx ;AN007; ;AN005; bx=STDIN. For search string + call get_cp ;AN005; Get the code page + jc open_read ;AN005; Error condition + mov ax,cs:cp ;AN005; Save code page value + mov cs:str_cp,ax ;AN005; .. + +;--------------------- +;- OPEN FILE FOR READING +;--------------------- +open_read: + push cs ;Load new DS with CS + pop ds + cmp cs:got_filename,TRUE ;AN004; using STDIN + je o_cont ;AN004; no, open the file + xor ax,ax ;AN007; ;AN004; file handle (ax) = STDIN + jmp short cp_check ;AN007; ;AN004; skip open of file +o_cont: ;AN004; + mov dx,cs:file_name_buf ;AC000;addrss. of the file name +openit: + mov ah,open + mov al,0 ;file open for reading + int 021h ;call the DOS + ljc do_open_error ;AN000; +;-------Open was successful. Make sure codepages are the same +cp_check: + cmp cs:cpsw_state,CPSWNotActive ;AN000; Is Code Page support active + je say_name ;AN000; No, continue + + push ax ;AN000; Save source handle + mov bx,ax ;AN000; Source handle in BX + call get_cp ;AN000; Get codepage of source file + + mov ax,cs:cp ;AN000; Place source CP in ax + cmp ax,cs:str_cp ;AN005; search string code page = src file code page ? + je c_cont ;AN005; yes, they are the same, ok + and ax,ax ;AN007; ;AN005; src filename cp = 0 + je c_cont ;AN005; yes, this cp=0 is ok. + mov ax,msg_code_page_mismatch ;AN005; Error, code page mismatch + mov dh,1 ;AN005; message class + call display_and_die ;AN005; bye! +c_cont: + cmp ax,cs:tgt_cp ;AN000; Is same as target cp ? + je cp_match ;AN000; Yes? Do nothing + + mov bx,STDOUT ;AN000; Standard output device + call set_cp ;AN000; Set codepage to that of source +cp_match: + pop ax ;AN000; Restore handle +;--------------------- +;- PRINT FILE NAME +;--------------------- +say_name: + push ax ;save file handle + cmp cs:got_filename,FALSE ;AN004; using STDIN + je xx1 ;AN004; yes, don't print a filename + mov dx,offset heading + mov cl,cs:heading_len + xor ch,ch + call prout + + mov dx,cs:file_name_buf ;AC000; + mov cx,cs:file_name_len + call prout + + cmp cs:c_flag,TRUE ;count only flag set? + je xx1 + + mov dx,offset crlf + mov cx,2 + call prout +xx1: + pop ax + +;--------------------- +;- Fill Buffer for Matching +;--------------------- +fill: + mov bx,ax ;retrieve handle +refill: + mov dx,offset buffer ;data buffer addrss. + mov cx,buffer_size + mov ah,read + int 021h + jnc no_read_error ;if carry then read error + jmp read_error +no_read_error: + or ax,ax ;if ax=0 then all done + jnz Truncate +DoNullRead: + cmp cs:c_flag,TRUE ;count only flag set? + jne sj2 + call print_count +sj2: + and bx,bx ;Using STD IN? + jnz regular + jmp foo ;if so: all done, exit +regular: + mov ah,close ;otherwise close the file + int 021h + jmp scan_rest ;get another file + +do_open_error: + jmp open_error ;AN000; +;--------------------------- +; We have read in an entire buffer. Scan for a ^Z and terminate the buffer +; there. Change only CX +;--------------------------- +Truncate: + push di + push cx + push es + mov di,dx + mov cx,ax + mov ax,ds + mov es,ax + mov al,1Ah + CLD + repnz scasb +;--------------------------- +; If zero is set, the the previous character is a ^Z. If it is reset then +; the previous character is the end of buffer. With ^Z, we back up over the +; char. +;--------------------------- + jnz chop + dec di +chop: + mov ax,di + sub ax,dx ; get true length of buffer + pop es + pop cx + pop di + or ax,ax + jz DoNullRead + +;--------------------------- +;----- MATCH ROUTINE +;--------------------------- +;Note: If input is being taken from a file the stack contains +; (from top to bottom): +; - Pointer to the next command in the command line +; - Pointer to the program segment prefix (to be loaded into +; DS to access the command line. +; if the input is from the standard input then NONE of it will be +; in the stack. +;--------------------------- + +go_match: + push bx ;save the file handle + mov bp,offset buffer ;ptr to first line of file +;--------------------------- +; At this point we must check to make sure there is AT LEAST one LF in the +; buffer. If there is not, then we must insert one at the end so we +; don't get stuck trying to get one complete line in the buffer when +; we can't cause the buffer ain't big enough. +;--------------------------- + push ax ; Save true buffer size + mov cx,ax ; scan whole buffer + mov al,LF ; for a LF + mov di,bp ; start of buffer + repnz scasb + pop ax ; recover buffer size + mov di,ax ;displacement from beg of buffer + jnz last_line ; No line feeds, must insert one +;--------------------------- +; Check to see if we reached EOF (return from READ less than buffer_size). +; If EOF we must make sure we end with a CRLF pair. +;--------------------------- + cmp ax,buffer_size-1 ;last line of the file? + jg no_last_line ;nope +last_line: ;if yes, add a CRLF just in case + mov bx,bp + cmp byte ptr[bx+di-1],LF ;finished with a LF? + je no_last_line ;yes, it's an OK line. + mov byte ptr[bx+di],CR ;put a CR at the end of the data + inc di + mov byte ptr[bx+di],LF ;put a LF ... + inc di + +no_last_line: + push di ;save the # of chars. in the buffer + push bp + mov dx,cs:st_length ;length of the string arg. + dec dx ;adjust for later use + jmp short try_again + +more_stuff_o: + jmp more_stuff + +;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------; +;Note: at this point the stack contains (from top to bottom): +; - Stuff mentioned before +; - File Handle +; - Number of chars. left in the buffer from the next line. +; - Addrs. of the next line in the buffer. +; +; plus, DX has the adjusted length of the string argument. +; +; We are about to begin scanning a line. We start by determining if there is +; a complete line in the buffer. If so, we scan for the char. If NOT, we go +; and grab new info. +;--------------------------- +try_again: + pop bp ;addrs. of next line in the buffer + mov di,bp ;points to beg. of a line + pop cx ;get # of chars left in the buffer + mov bx,cx ;save in case a non-complete line + mov al,LF ;search for a Line Feed + jcxz more_stuff_o ;no chars left in buffer + repnz scasb + jnz more_stuff_o ;no full line left in buffer + push cx ;save chars left in buffer + push di ;points to beg. of next line + mov cx,di + sub cx,bp ;length of the current line + mov bx,cx ;save in case it has a match + dec cx ;Discount the LF we found + cmp byte ptr ES:[DI-2],CR ; Is there a CR to discount too? + jnz NO_SECOND_DEC ; No there is not. + dec cx ;CR character discounted +NO_SECOND_DEC: + inc cs:line_cntr ;increment line counter + jcxz try_again_opt ;if line empty go to next line + mov di,bp ;pointer to the beg. of current line +another_char: +;--------------------------- +; On entry: +; BX line length +; CX adjusted line length +; DX adjusted string argument length +; DI points to beg. of line +;--------------------------- + push dx ;save for next line +lop: + pop dx + push dx + inc dx ;different algorithm! + mov si,offset st_buffer ;pointer to beg. of string argument + +comp_next_char: + push di + mov di,si + call is_prefix ;check for a prefix char + pop di + jnc nopre + lodsw + cmp cx,1 ; Can not compare a two byte char + jbe try_again_opt1 ; if there is only one available + cmp ax,word ptr [di] + jz kmatch1 + jmp short back_up ;AN007; + +nopre: + lodsb + cmp al,byte ptr [di] + jz kmatch +back_up: + pop ax ; Original length of comp string + push ax + inc ax +;--------------------------- + ; Our match failed IN THE MIDDLE of the string (partial match). We need + ; to back up in the line to the NEXT char after the one which matched + ; the first char of the search string and try again. The amount to + ; back up to where we started is ax-dx (the result MAY be 0, this is OK). + ; we then need to skip ONE char in the line. +;--------------------------- + sub ax,dx ; AX = AX-DX + sub di,ax ; Do the back up. + add cx,ax ; restore count too! + call next_kchar ;no match, advance di to next kanji + jc try_again_opt1 ;not enough chars left in line + jmp short lop ;try another char in line + +try_again_opt1: + pop dx + jmp short try_again_opt ;AN007; + + +kmatch1: + dec dx ;last char had prefix so it was + ; long. +kmatch: + dec dx + jz a_matchk ; no chars left: a match! + call next_kchar + jc try_again_opt1 + jmp comp_next_char ; loop if chars left in arg. + +a_matchk: + pop dx + cmp cs:v_flag,TRUE ;is flag set? + jne prt_line ;no, print the line + jmp try_again + +;--------------------------- +;- NO MATCH: CHECK FOR THE v OPTION +;--------------------------- +try_again_opt: + cmp cs:v_flag,TRUE ;is flag set? + jne try_again ;no goto next line + +;--------------------------- +;- PRINT THE LINE WITH THE MATCH +;Note: at this point the stack contains (top to bottom) +; - Stuff mentioned before +; +; plus, BP points to begginig of the current line, BX has the length +;of the current line including the CRLF, and DX the adjusted length of +;the string argument. +;--------------------------- + +prt_line: + cmp cs:c_flag,TRUE ;is count only flag set? + jne no_c_flg + inc cs:mtch_cntr ;yes, increment counter + jmp try_again + +no_c_flg: + push dx ;save the adjusted string arg. length + cmp cs:n_flag,TRUE ;is line number flag set? + jne no_n_flg + call prt_lcntr +no_n_flg: + mov dx,bp + mov cx,bx + call prout + pop dx ;restore + jmp try_again + +;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------; +; The scanning routines have detected that the buffer does not +;contain a full line any more. More lines have to be read into the +;buffer. But first perform a seek on the file in order to re-read +;the non-complete line into the begining of the buffer. +; Uppon entry BP contains points to the begining of the non-complete +;line, and BX has the number of characters left in the buffer. +; The Stack contains (top to bottom): +; - Pointer to the next command in the command line +; - Pointer to the program segment prefix (to be loaded into +; DS to access the command line). +; - File handle. + +more_stuff: + mov dx,bx ;get chars left in buffer + pop bx ;get the handle + or dx,dx ;are there 0 left? + jz no_seek ;yes, do not seek + neg dx ;form two's complement + mov cx,-1 + mov al,1 ;seek from the current position + mov ah,lseek ;seek on file + int 021h + jc read_error +no_seek: + jmp refill ;no errors: refill the buffer +read_error: + and bx,bx ;AN007; ;Using STD IN? + je foo ;if so: all done, exit + mov ah,close ;close the file + int 021h +;--------------- +;------ Set message number and go display it + + mov ax,msg_read_error ;AN000; Read error message + jmp short r_error ;AN007; + +;--------------------- +;- PRINT ERRORS +;--------------------- +open_error: + cmp ax,ERROR_ACCESS_DENIED ;AN000; + jnz DoNorm + + mov ax,msg_access_denied ;AN000; Message for Access Denied + jmp short r_error ;AN007; ;AN000; Do the rest + +DoNorm: ;AN000; + mov ax,msg_file_not_found ;AN000; Message for File Not Found + +r_error: + call prt_find ;AN005; + mov cs:sl_ptr_s,ds ;AN000; Save segment of subst text + mov cx,cs:file_name_buf ;AN000; + mov cs:sl_ptr_o,cx ;AN000; Save offset of subst text + mov cs:sl_flag,left_align+char_field_ASCIIZ ;AN000; Type of insertion text + mov bx,STDERR ;AN000; Sent to STD OUT + mov cx,1 ;AN000; One substitution string + mov dh,1 ;AN000; Its a utility message + + call display_msg ;AN000; Display rror message + +;--------------------- +;- SCAN THE REST OF THE COMMAND LINE +;--------------------- +scan_rest: + pop ds ;restore pointer to comm. line + pop si ;restore pointer to next comm. + mov cs:did_file,TRUE ;AN004; tell parser we did a file, so if it doesn't find another, ok! + cmp cs:got_eol,TRUE ;AN004; Check if nothing left on command line + je foo ;AN004; no, nothing left on command line, exit + jmp parser + +foo: + mov cs:errlevel,ERRORLEVEL_ZERO ;AN000; Proper code + call terminate ;AN000; reset codepage and terminate + + +;-------------------------- +; Clear Counters +;-------------------------- +clr_cntrs proc near + mov byte ptr cs:mtch_cntr,0 + mov byte ptr cs:line_cntr,0 + ret +clr_cntrs endp + + +;-------------------------- +; Print Count of Matched lines +; Modifies: AX,CX,DX and DI +;-------------------------- +print_count proc near + push bx ;save handle + and bx,bx ;AN007; ;using STDIN? + jz sj3 ;if so do not print file name + + mov dx,offset ccolon + mov cx,2 + call prout ;print colon +sj3: + mov ax,cs:mtch_cntr + mov di,offset n2_buf ;buffer for characters + call bin2asc ;convert to ascii + mov dx,offset n2_buf + call prout ;print the number + mov dx,offset crlf + mov cx,2 + call prout ;print an end of line + pop bx + ret +print_count endp + +;-------------------------- +; Print relative line number + +; Modifies: AX,CX and DI +;-------------------------- +prt_lcntr proc near + push bx + push dx + mov ax,cs:line_cntr + mov di,offset n2_buf + call bin2asc + mov byte ptr[di],"]" + inc cx + inc cx + mov dx,offset n1_buf + call prout + pop dx + pop bx + ret +prt_lcntr endp + +;-------------------------- +; Print string to STDOUT +;-------------------------- +prout proc near + mov bx,STDOUT + mov ah,write + int 021h + ret +prout endp + +;-------------------------- +; Binary to Ascii conversion routine +; Entry: +; AX Binary number +; DI Points to one past the last char in the +; result buffer. +; Exit: +; Result in the buffer MSD first +; CX Digit count +; Modifies: +; AX,BX,CX,DX and DI +;-------------------------- +bin2asc proc near + mov bx,0ah + xor cx,cx +go_div: + inc cx + cmp ax,bx + jb div_done + xor dx,dx + div bx + add dl,'0' ;convert to ASCII + push dx + jmp short go_div + +div_done: + add al,'0' + push ax + mov bx,cx +deposit: + pop ax + stosb + loop deposit + mov cx,bx + ret +bin2asc endp + +;-------------------------- +; CAPIALIZES THE CHARACTER IN AL +; entry: +; AL has the character to Capitalize +; exit: +; AL has the capitalized character +; modifies: +; AL +;-------------------------- +;make_caps proc near +; cmp al,'a' +; jb no_cap +; cmp al,'z' +; jg no_cap +; and al,0dfh +;no_cap: +; ret +;make_caps endp +; + + +;-------------------------- +; ADVANCE POINTER TO NEXT KANJI CHARACTER +; entry: DI points to a Kanji string +; CX length in bytes of the string +; exit: DI points to next Kanji char +; CX has number of bytes left +; modifies: AX +;-------------------------- +next_kchar proc near + jcxz no_kleft + call is_prefix + jnc no_p + inc di + dec cx + jcxz no_kleft ; for insurance +no_p: + inc di + dec cx + clc + ret + +no_kleft: + stc + ret +next_kchar endp + +;-------------------------- +; Get DOS dbcs table vector +; entry: none +; exit: none +; modifies: none +;-------------------------- +get_dbcs_vector proc near ;AN006; + push es ;AN006; + push di ;AN006; + push ax ;AN006; + push bx ;AN006; + push cx ;AN006; + push dx ;AN006; +; + mov ax,cs ;AN006; ;segment of return buffer + mov es,ax ;AN006; + mov di,offset bufferDB ;AN006; ;offset of return buffer + mov ah,65h ;AN006; ;get extended country info + mov al,07h ;AN006; ;get DBCS environment table + mov bx,0ffffh ;AN006; ;use active code page + mov cx,5 ;AN006; ;number of bytes returned + mov dx,0ffffh ;AN006; ;default country ID + int 21h ;AN006; ;DOS function call,vector returned + ;AN006; ; in ES:DI + inc di ;AN006; ;skip over id byte returned + mov ax,word ptr es:[di] ;AN006; ;get offset of DBCS table + mov cs:dbcs_off,ax ;AN006; ;save it +; + add di,2 ;AN006; ;skip over offset to get segment + mov bx,word ptr es:[di] ;AN006; ;get segment of DBCS table + mov cs:dbcs_seg,bx ;AN006; ;save it +; + mov di,ax ;AN006; ;Point to DBCS table to get length + mov es,bx ;AN006; + mov ax,word ptr es:[di] ;AN006; + mov cs:dbcs_len,ax ;AN006; + add cs:dbcs_off,2 ;AN006; ;change offset to point to table +; + pop dx ;AN006; + pop cx ;AN006; + pop bx ;AN006; + pop ax ;AN006; + pop di ;AN006; + pop es ;AN006; +; + ret ;AN006; +get_dbcs_vector endp ;AN006; + + +;-------------------------- +; FIND OUT IS THE BYTE IS A KANJI PREFIX +; entry: DI points to a kanji string +; exit: Carry set if it is a kanji prefix +; modifies: AX +;-------------------------- +is_prefix proc near ;AN006; + push es + push si + push ax +; + mov si,cs:dbcs_off ;ES:SI -> DOS dbcs table + mov ax,cs:dbcs_seg + mov es,ax +; + mov al,byte ptr cs:[di] ;get first byte of string +; +; Two consecutive 00 bytes signifies end of table +; + +is_loop: + cmp word ptr es:[si],00h ;Check for two consecutive 00 bytes + jne is_next1 ;no, continue + clc ;clear carry - byte is not lead byte of db char + jmp short is_exit ;AN007; ;yes, found them, quit + +; +; Check if byte is within range values of DOS dbcs table +; + +is_next1: + cmp al,byte ptr es:[si] ;is byte >= first byte in range? + jae is_next2 ;yes, continue + jmp short is_again ;AN007; ;no, loop again + +is_next2: + cmp al,byte ptr es:[si+1] ;is byte <= last byte in range? + jbe is_found ;yes, found a lead byte of db char + +is_again: + add si,2 ;no, increment ptr to next range + jmp is_loop + +is_found: + stc ;byte is lead byte of db char, set carry + +is_exit: + pop ax + pop si + pop es +; + ret +is_prefix endp + + +; +;--------------------- +;- Terminate process +;--------------------- +terminate proc near ;AN000; + mov ah,exit ;AN000; Terminate function call + mov al,cs:errlevel ;AN000; Errorlevel placed in AL + int 021h ;AN000; Terminate + ret ;AN000; Meaningless return +terminate endp ;AN000; + +; +;************************************************************ +;* +;* SUBROUTINE NAME: set_cp +;* +;* FUNCTION: Sets the cp of the handle in bx to the cp in LIST structure +;* +;* INPUT: +;* BX = handle +;* cp_list.cp = code page to set for the file handle in BX +;* +;* OUTPUT: +;* Codepage will be set to that requested, or an error will be +;* returned in AX with carry flag set. +;* +;************************************************************ +set_cp proc near ;AN000; + mov ax,SetExtAttr ;AN000; Set target codepage to that of source + mov di,offset cp_list ;AC001; Input buffer address + int 021h ;AN000; Call DOS + ret ;AN000; Return to caller +set_cp endp ;AN000; + + + +;************************************************************ +;* +;* SUBROUTINE NAME: get_cp +;* +;* FUNCTION: Gets the cp of the handle in bx +;* +;* INPUT: +;* BX = handle +;* +;* OUTPUT: +;* Codepage for the file handle in bx will be returned in +;* the CP_LIST.CP structure, or an error will be returned in +;* AX with carry flag set. +;* +;************************************************************ +get_cp proc near ;AN000; + push ds ;AN005; + + push cs ;AN005; + pop ds ;AN005; + + mov ax,GetExtAttr ;AN000; Get codepage + mov di,offset cp_list ;AN000; Input buffer address + mov si,offset cp_qlist ;AN001; which ea to select + mov cx,cp_len ;AN001; buffer length + int 021h ;AN000; Call to DOS + + pop ds ;AN005; + ret ;AN000; Return to caller +get_cp endp ;AN000; + + +; +;************************************************************ +;* +;* SUBROUTINE NAME: display_msg +;* +;* SUBROUTINE FUNCTION: +;* Display the requested message to the specified handle +;* +;* INPUT: +;* 1) AX = Number of the message to be displayed. +;* 2) BX = Handle to be written to. +;* 3) DH = Code indicating message class +;* +;* OUTPUT: +;* The message corresponding to the requested msg number will +;* be written to the requested handle. +;* +;* NORMAL EXIT: +;* Message will be successfully written to requested handle. +;* +;* ERROR EXIT: +;* None. Note that theoretically an error can be returned from +;* SYSDISPMSG, but there is nothing that the application can do. +;* +;* INTERNAL REFERENCES: +;* System Display Message service routines +;* +;* EXTERNAL REFERENCES: +;* None +;* +;************************************************************ +display_msg proc near ;AN000; + push ds ;AN000; Save DS + push cs ;AN000; Substitution list segment + pop ds ;AN000; + mov si,offset sublist ;AN000; Substitution list offset + ; mov dh,-1 ;AN000; Message class + ; 1=DOS Extended error + ; 2=DOS Parse error + ; -1=Utility message + mov dl,0 ;AN000; DOS INT 21H function number to use for input + ; 00H=No input, 01H=Keyboard input, + ; 07H=Direct Console Input Without Echo, + ; 08H=Console Input Without Echo, 0AH=Buffered Keyboard Input + call SYSDISPMSG ;AN000; AX=Extended key value if wait for key + ; jnc disp_done ;AN000; If CARRY SET then registers will contain extended error information + ; AX - Extended error Number + ; BH - Error Class + ; BL - Suggested action + ; CH - Locus +disp_done: ;AN000; + pop ds ;AN000; Restore DS + ret ;AN000; +display_msg ENDP ;AN000; + + PAGE +;************************************************************ +;* +;* SUBROUTINE NAME: parse +;* +;* SUBROUTINE FUNCTION: +;* Call the DOS PARSE Service Routines to process the command +;* line. Search for valid switches (/N, /V, and /C) and take +;* appropriate action for each. Extract the search string. +;* +;* INPUT: DS:SI points to string to parse +;* ES:DI parser parms +;* +;* OUTPUT: ES:DI points to filespec for text search +;* +;* NORMAL EXIT: +;* +;* If /V, /C, or /N entered, set appropriate flag. +;* Save the search string. +;* +;* ERROR EXIT: +;* +;* If user enters any invalid parameter or switch, then this +;* routine will display an error message and terminate with +;* errorlevel 1. +;* +;************************************************************ +EOL equ -1 ;AN000; Indicator for End-Of-Line +NOERROR equ 0 ;AN000; Return Indicator for No Errors +SYNTAX equ 9 ;AN000; Syntax error from parser + +SWITCH equ 3 ;AN000; +FILESPEC equ 5 ;AN000; +QUOTED_STRING equ 9 ;AN000; + +parse proc near ;AN000; +;-------------------------------------- +; address of command line in DS:SI +;-------------------------------------- +;------------------------------------------ +;- Look for the search string and switches +;------------------------------------------ +parse_loop: ;AN000; + mov di,offset parms ;AN000; Address of parse control block at ES:DI + xor dx,dx ;AN000; Reserved + call sysparse ;AN000; Parse parm at DS:SI + cmp ax,EOL ;AN000; Are we at End Of Line ?? + jne p_next ;AN004; No eol found + mov cs:got_eol,TRUE ;AN004; no more filenames to get! + cmp cs:did_file,TRUE ;AN004; did we do a file already ? + lje doexit ;AN004; yes, exit + jmp end_parse ;AN004; Yes, done here +p_next: ;AN004; continue + and ax,ax ;AN007; ;AN000; Was there an error? + je CONT2 ;AN000; No, continue processing + + mov dh,2 ;AN005; Its a PARSE message + call display_and_die ;AN005; +CONT2: ;AN000; Something valid was entered + cmp cs:rb_type,QUOTED_STRING ;AN000; Is it a quoted string ? + je its_a_quoted_string ;AN000; Yes, go process it + cmp cs:rb_type,FILESPEC ;AN000; Is it a filespec? + jne cont3 ;AN000; + mov di,cs:rb_value_lo ;AN000; Look for another + mov cs:got_filename,TRUE ;AN004; got a filename + jmp short end_parse ;AN007; ;AN000; Look for another +cont3: + cmp cs:rb_type,SWITCH ;AN000; Is it a switch ? + je its_a_switch ;AN000; Yes, go process it + mov ax,msg_inv_parm ;AN000; None of above, too bad + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Tell the poor user and terminate + +;----------------------------- +;- The search string was entered +;----------------------------- +its_a_quoted_string: ;AN000; Found a quoted string + cmp cs:got_srch_str,TRUE ;AN000; Do we already have one? + jne its_ok ;AN000; No, it's ok + mov ax,msg_inv_parm ;AN000; Yes, Invalid parm! + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Tell user and die gracefully +its_ok: ;AN000; + mov di,cs:rb_value_lo ;AN000; Get pointer to it + mov bx,offset st_buffer ;AN000; save buffer offset + call get_length ;AN000; get string length + mov cs:st_length,ax ;AN000; save length + mov cs:got_srch_str,TRUE ;AN000; Indicate that we have it + jmp parse_loop ;AN000; + +;----------------------------- +;- A valid switch was entered +;----------------------------- +its_a_switch: ;AN000; + mov bx,cs:rb_synonym ;AN000; Get offset of switch entered + cmp bx,offset n_swch ;AN000; Is it the /N switch? + jne chek_v ;AN000: Yes, process it. + jmp parse_loop ;AN000; Look for another +chek_v: ;AN000; + cmp bx,offset v_swch ;AN000; Is it the /N switch? + jne chek_c ;AN000: Yes, process it. + jmp parse_loop ;AN000; Look for another +chek_c: ;AN000; + cmp bx,offset c_swch ;AN000; Is it the /N switch? + jne whoops ;AN000: Yes, process it. + jmp parse_loop ;AN000; Look for another +whoops: ;AN000; None of the above (can we ever get here?) + mov ax,msg_switch ;AN000; Invalid parameter + mov dh,2 ;AN005; message class + call display_and_die ;AN000; Yes, tell the poor user and terminate + +end_parse: ;AN000; A filename should be next + cmp cs:got_srch_str,TRUE ;AN000; Do we already have one? + je rett ;AN000; + mov ax,msg_required_missing ;AN005; + mov dh,-1 ;AN005; message class + call display_and_die ;AN000; Yes, tell the poor user and terminate +rett: ;AN000; + ret ;AN000; + +doexit: + mov cs:errlevel,ERRORLEVEL_ZERO;AN000; Proper code + call terminate ;AN000; reset codepage and terminate + +parse endp ;AN000; + + +;------------------------------------ +;- +;- Procedure name: pre_parse +;- +;- Purpose: parse for all switches now +;- so that they can be applied for +;- all filenames on command line. +;- +;- INPUT: none +;- +;------------------------------------ +pre_parse proc near ;AN005; + push ax ;AN005; + push bx ;AN005; + push cx ;AN005; + push dx ;AN005; + push di ;AN005; + push si ;AN005; + push es ;AN005; + push ds ;AN005; +; +pp_loop: ;AN005; + mov di,offset parms1 ;AN005; Address of parse control block at ES:DI + xor dx,dx ;AN005; Reserved + call sysparse ;AN005; Parse parm at DS:SI + + cmp ax,EOL ;AN005; Are we at End Of Line ?? + je pp_end ;AN005; No eol found + + cmp ax,SWITCH ;AN005; invalid switch ? + jne pp_next ;AN005; no +; error + mov ax,msg_switch ;AN005; Invalid switch + mov dh,2 ;AN005; message class + call display_and_die ;AN005; Yes, tell the poor user and terminate +pp_next: + and ax,ax ;AN007; ;AN005; Was there an error? + jne pp_loop ;AN005; No, continue processing + + cmp cs:rb_type,SWITCH ;AN005; Is it a switch ? + jne pp_loop ;AN005; + +; got a switch + mov bx,cs:rb_synonym ;AN005; Get offset of switch entered + cmp bx,offset n_swch ;AN005; Is it the /N switch? + jne pp_chek_v ;AN005: Yes, process it. + mov cs:n_flag,TRUE ;AN005; Set the corresponding flag + jmp pp_loop ;AN005; Look for another +pp_chek_v: ;AN005; + cmp bx,offset v_swch ;AN005; Is it the /N switch? + jne pp_chek_c ;AN005: Yes, process it. + mov cs:v_flag,TRUE ;AN005; Set the corresponding flag + jmp pp_loop ;AN005; Look for another +pp_chek_c: ;AN005; + cmp bx,offset c_swch ;AN005; Is it the /N switch? + jne pp_error ;AN005: Yes, process it. + mov cs:c_flag,TRUE ;AN005; Set the corresponding flag + jmp pp_loop ;AN005; Look for another + +pp_error: ;AN005; None of the above (can we ever get here?) + mov ax,msg_switch ;AN005; Invalid parameter + mov dh,2 ;AN005; message class + call display_and_die ;AN005; Yes, tell the poor user and terminate + +pp_end: ;AN005; A filename should be next + pop ds ;AN005; + pop es ;AN005; + pop si ;AN005; + pop di ;AN005; + pop dx ;AN005; + pop cx ;AN005; + pop bx ;AN005; + pop ax ;AN005; +; + ret ;AN005; +pre_parse endp ;AN005; + + +;------------------------------------ +;- +;- Procedure name: prt_find +;- +;- Purpose: When FIND is used as a filter, +;- then display error messages with the +;- prefix: "FIND: ". +;- +;- INPUT: none +;- +;------------------------------------ +prt_find proc near ;AN005; + cmp cs:got_filename,TRUE ;AN005; Check if should print "FIND:" + je prt_ret ;AN005; + push ax ;AN005; Save error + push dx ;AN005; + mov dh,-1 ;AN005; Display FIND: + mov ax,msg_find ;AN005; + xor cx,cx ;AN007; ;AN005; No substitution text + mov bx,STDERR ;AN005; Sent to STD OUT + call display_msg ;AN005; Display the message + pop dx ;AN005; + pop ax ;AN005; Restore error +prt_ret: + ret ;AN005; +prt_find endp ;AN005; + + +;------------------------------------ +;- +;- Procedure name: display_and_die +;- +;- Purpose: Called when the parser finds that +;- required arguments were not entered +;- from the command line. +;- +;- INPUT: AX = Error number +;- +;------------------------------------ +display_and_die proc near + call prt_find ;AN005; + xor cx,cx ;AN007; ;AN000; No substitution text + mov cs:errlevel,ERRORLEVEL_TWO ;AC005; Error code for exit + + mov bx,STDERR ;AN000; Sent to STD OUT + call display_msg ;AN000; Display the message + call terminate ;AN000; and Terminate + ret ;AN000; +display_and_die endp + +;------------------------------------ +;- +;- Procedure name: get_length +;- +;- Purpose: determine the length of a null +;- ending string. +;- +;- INPUT: ES:DI = string address +;- ES:BX = save address (0=no save) +;- +;- OUTPUT: AX = length of string +;------------------------------------ +get_length proc near + push di + push bx + push dx + xor ax,ax ;init string length +look_str: + mov dl,es:[di] ;get character + or bx,bx ;save it? + jz no_save + mov es:[bx],dl ;save character + inc bx ;save next character +no_save: ;AN007; + and dl,dl ;AN007; ;check for eol (asciiz string) + je done_look ;if so, exit + cmp dl,0dh ;AN005; check for eol (carriage return) + je done_look ;AN005; + inc ax ;increment length + inc di ;look at next character + jmp look_str +done_look: + pop dx + pop bx + pop di + ret +get_length endp + + + + +; +;----- BUFFER AREA -------- +st_length dw 0 ;String argument length +st_buffer db st_buf_size dup(?) ;String argument buffer + +file_name_len dw 0 ;File name length +file_name_buf dw 0 ;File name buffer offset + +buffer db buffer_size+2 dup(?) ;file data buffer + +include msgdcl.inc + +code ends + +;-------------------------- +;--- STACK SEGMENT --- +;-------------------------- +stack segment para stack 'STACK' + dw (362 - 80h) +64 dup(?,?) ;(362 - 80h) == New - old IBM ROM +stack_top equ $ +stack ends + + end start + -- cgit v1.2.3