diff options
Diffstat (limited to 'v4.0/src/CMD/FIND/FIND.ASM')
| -rw-r--r-- | v4.0/src/CMD/FIND/FIND.ASM | 1664 |
1 files changed, 1664 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FIND/FIND.ASM b/v4.0/src/CMD/FIND/FIND.ASM new file mode 100644 index 0000000..459765a --- /dev/null +++ b/v4.0/src/CMD/FIND/FIND.ASM | |||
| @@ -0,0 +1,1664 @@ | |||
| 1 | title DOS FIND Utility | ||
| 2 | ; 0 | ||
| 3 | ;******************************************************************** | ||
| 4 | ;* | ||
| 5 | ;* UTILITY NAME: find.exe | ||
| 6 | ;* | ||
| 7 | ;* SOURCE FILE NAME: find.asm | ||
| 8 | ;* | ||
| 9 | ;* STATUS: Find utility, DOS Version 4.0 | ||
| 10 | ;* | ||
| 11 | ;* SYNTAX (Command line) | ||
| 12 | ;* | ||
| 13 | ;* FIND [/V][/C][/N] "string" [[d:][path]filename[.ext]...] | ||
| 14 | ;* | ||
| 15 | ;* where: | ||
| 16 | ;* | ||
| 17 | ;* /V - Display all lines NOT containing the string | ||
| 18 | ;* /C - Display only a count of lines containing string | ||
| 19 | ;* /N - Display number of line containing string | ||
| 20 | ;* | ||
| 21 | ;* | ||
| 22 | ;* UTILITY FUNCTION: | ||
| 23 | ;* | ||
| 24 | ;* Searches the specified file(s) looking for the string the user | ||
| 25 | ;* entered from the command line. If file name(s) are specifeied, | ||
| 26 | ;* those names are displayed, and if the string is found, then the | ||
| 27 | ;* entire line containing that string will be displayed. Optional | ||
| 28 | ;* parameters modify that behavior and are described above. String | ||
| 29 | ;* arguments have to be enclosed in double quotes. (Two double quotes | ||
| 30 | ;* if a double quote is to be included). Only one string argument is | ||
| 31 | ;* presently allowed. The maximum line size is determined by buffer | ||
| 32 | ;* size. Bigger lines will bomb the program. If no file name is given | ||
| 33 | ;* then it will asssume the input is coming from the standard Input. | ||
| 34 | ;* No errors are reported when reading from standard Input. | ||
| 35 | ;* | ||
| 36 | ;* | ||
| 37 | ;* EXIT: | ||
| 38 | ;* The program returns errorlevel: | ||
| 39 | ;* 0 - OK, and some matches | ||
| 40 | ;* 1 - | ||
| 41 | ;* 2 - Some Error | ||
| 42 | ;* | ||
| 43 | ;* | ||
| 44 | ;* Revision History: | ||
| 45 | ;* | ||
| 46 | ;* V1.1 8/23/82 M.A.U. (Microsoft) | ||
| 47 | ;* | ||
| 48 | ;* V1.2 9/22/82 M.A.U. (Microsoft) | ||
| 49 | ;* Added the -c and -n options | ||
| 50 | ;* | ||
| 51 | ;* 9/23/82 M.A.U. (Microsoft) | ||
| 52 | ;* Added DOS version number control | ||
| 53 | ;* | ||
| 54 | ;* 10/07/82 Rev.2 M.A.U. (Microsoft) | ||
| 55 | ;* Changed quote for double quotes, and added | ||
| 56 | ;* file name printing | ||
| 57 | ;* | ||
| 58 | ;* 10/20/82 Rev.3 M.A.U. (Microsoft) | ||
| 59 | ;* Modified IBM name to FIND, and changed the text | ||
| 60 | ;* of some messages. | ||
| 61 | ;* | ||
| 62 | ;* 10/25/82 Rev.4 M.A.U. (Microsoft) | ||
| 63 | ;* Changed name to FIND and all messages to the | ||
| 64 | ;* IBM form. | ||
| 65 | ;* | ||
| 66 | ;* 10/27/82 Rev.5 M.A.U. (Microsoft) | ||
| 67 | ;* Made the correct exit on version check in case | ||
| 68 | ;* of a 1.x DOS. | ||
| 69 | ;* | ||
| 70 | ;* 11/4/82 Rev. 5 A.R. Reynolds (Microsoft) | ||
| 71 | ;* Messages moved to external module | ||
| 72 | ;* | ||
| 73 | ;* 11/10/82 Rev. 6 M.A. U. (Microsoft) | ||
| 74 | ;* Corrected problem with line numbers, and a problem | ||
| 75 | ;* with seeking for 0 chars. | ||
| 76 | ;* | ||
| 77 | ;* 03/30/83 Rev. 7 M.A. U. (Microsoft) | ||
| 78 | ;* Added patch area for bug fixing. | ||
| 79 | ;* | ||
| 80 | ;* 04/14/83 Rev. 8 M.A. U. (Microsoft) | ||
| 81 | ;* Made changes for Kanji characters. (ugh!) | ||
| 82 | ;* | ||
| 83 | ;* 12/17/84 Rev. 9 Zibo (Microsoft) | ||
| 84 | ;* Fix boundary case for buffer containing exact line | ||
| 85 | ;* | ||
| 86 | ;* V4.0 : 6/29/87 Russ W (IBM) | ||
| 87 | ;* Lines commented with ;AN000; | ||
| 88 | ;* Add support for IBM Parse service routines | ||
| 89 | ;* Add support for IBM Message Retriever Service Routines | ||
| 90 | ;* Add support for Code Page File Tags | ||
| 91 | ;* Made PROCs out of all labels that were targets of a call (not commented with AN000) | ||
| 92 | ;* Removed patch area for "bug fixing" | ||
| 93 | ;* | ||
| 94 | ;* V4.0 : 9/15/87 Bill L, (IBM) | ||
| 95 | ;* ;AN001; = DCR 201, changes to extended attributes support | ||
| 96 | ;* ;AN002; = PTM 1090 | ||
| 97 | ;* ;AN003; = DCR 191 | ||
| 98 | ;* ;AN004; = PTM 1630 | ||
| 99 | ;* ;AN005; = PTM 1643, PTM 1675, PTM 1754 | ||
| 100 | ;* ;AN006; = DBCS support | ||
| 101 | ;* ;AN007; = Optimizations to save disk space on ship diskettes | ||
| 102 | ;* | ||
| 103 | ;********************************************************************** | ||
| 104 | |||
| 105 | ;-------------------------- | ||
| 106 | ;- MACRO DEFINITIONS | ||
| 107 | ;-------------------------- | ||
| 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 | ; | ||
| 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 | ; | ||
| 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 | ; | ||
| 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 | ; | ||
| 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 | ; | ||
| 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 | ; | ||
| 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 | |||