diff options
Diffstat (limited to 'v2.0/source/FIND.ASM')
| -rw-r--r-- | v2.0/source/FIND.ASM | 932 |
1 files changed, 932 insertions, 0 deletions
diff --git a/v2.0/source/FIND.ASM b/v2.0/source/FIND.ASM new file mode 100644 index 0000000..7c82768 --- /dev/null +++ b/v2.0/source/FIND.ASM | |||
| @@ -0,0 +1,932 @@ | |||
| 1 | title MSDOS V2.0 FIND | ||
| 2 | |||
| 3 | ;--------------------------------------------------------------------; | ||
| 4 | ; Revision History: ; | ||
| 5 | ; ; | ||
| 6 | ; V1.1 8/23/82 M.A.Ulloa ; | ||
| 7 | ; ; | ||
| 8 | ; V1.2 9/22/82 M.A.Ulloa ; | ||
| 9 | ; Added the -c and -n options ; | ||
| 10 | ; ; | ||
| 11 | ; 9/23/82 M.A.Ulloa ; | ||
| 12 | ; Added DOS version number control ; | ||
| 13 | ; ; | ||
| 14 | ; 10/07/82 Rev.2 M.A.Ulloa ; | ||
| 15 | ; Changed quote for double quotes, and added ; | ||
| 16 | ; file name printing ; | ||
| 17 | ; ; | ||
| 18 | ; 10/20/82 Rev.3 M.A.Ulloa ; | ||
| 19 | ; Modified IBM name to FIND, and changed the text ; | ||
| 20 | ; of some messages. ; | ||
| 21 | ; ; | ||
| 22 | ; 10/25/82 Rev.4 M.A.Ulloa ; | ||
| 23 | ; Changed name to FIND and all messages to the ; | ||
| 24 | ; IBM form. ; | ||
| 25 | ; ; | ||
| 26 | ; 10/27/82 Rev.5 M.A.Ulloa ; | ||
| 27 | ; Made the correct exit on version check in case ; | ||
| 28 | ; of a 1.x DOS. ; | ||
| 29 | ; ; | ||
| 30 | ; 11/4/82 Rev. 5 A.R. Reynolds ; | ||
| 31 | ; Messages moved to external module ; | ||
| 32 | ; ; | ||
| 33 | ; 11/10/82 Rev. 6 M.A. Ulloa ; | ||
| 34 | ; Corrected problem with line numbers, and a problem ; | ||
| 35 | ; with seeking for 0 chars. ; | ||
| 36 | ; ; | ||
| 37 | ; 03/30/83 Rev. 7 M.A. Ulloa ; | ||
| 38 | ; Added patch area for bug fixing. ; | ||
| 39 | ; ; | ||
| 40 | ; 04/14/83 Rev. 8 M.A. Ulloa ; | ||
| 41 | ; Made changes for Kanji characters. (uhg!) ; | ||
| 42 | ; ; | ||
| 43 | ;--------------------------------------------------------------------; | ||
| 44 | |||
| 45 | FALSE equ 0 | ||
| 46 | TRUE equ NOT FALSE | ||
| 47 | |||
| 48 | KANJI equ FALSE ;set to true is kanji vers. | ||
| 49 | |||
| 50 | ;--------------------------------------------------------------------; | ||
| 51 | ; FIND program following the standart UNIX operation. ; | ||
| 52 | ; ; | ||
| 53 | ; FORMAT: ; | ||
| 54 | ; find {option} string {filename {filename} {...}} ; | ||
| 55 | ; ; | ||
| 56 | ; NOTES: ; | ||
| 57 | ; 1) String arguments HAVE to be enclosed ; | ||
| 58 | ; in double quotes. (Two double quotes if a ; | ||
| 59 | ; doble quote is to be included). Only ONE ; | ||
| 60 | ; string argument is presently allowed. ; | ||
| 61 | ; ; | ||
| 62 | ; 2) Options are available: ; | ||
| 63 | ; v All lines but those matching are considered ; | ||
| 64 | ; c Only print a count of matching lines ; | ||
| 65 | ; n Each line is preceded by its relative ; | ||
| 66 | ; line number in the file. ; | ||
| 67 | ; ; | ||
| 68 | ; - Options can be Upper or lower case. ; | ||
| 69 | ; - Format: The switch character followed by an options ; | ||
| 70 | ; character. I.e.: In the IBM PC: /v ; | ||
| 71 | ; ; | ||
| 72 | ; 3) The program returns: ; | ||
| 73 | ; 0 - OK, and some matches ; | ||
| 74 | ; 2 - Some Error ; | ||
| 75 | ; ; | ||
| 76 | ; 4) The maximum line size is determined by ; | ||
| 77 | ; buffer size. Bigger lines will bomb the program. ; | ||
| 78 | ; ; | ||
| 79 | ; 5) If no file name is given then it will asssume ; | ||
| 80 | ; the input is comming from the Standart Input. NO ; | ||
| 81 | ; errors are reported when reading from Standart Input. ; | ||
| 82 | ;--------------------------------------------------------------------; | ||
| 83 | |||
| 84 | code segment public | ||
| 85 | assume cs:code,ss:code,ds:nothing,es:nothing | ||
| 86 | |||
| 87 | |||
| 88 | CR equ 0dh ;A Carriage Return | ||
| 89 | LF equ 0ah ;A Line Feed | ||
| 90 | quote_char equ 22h ;A double quote character | ||
| 91 | |||
| 92 | |||
| 93 | buffer_size equ 4096 ;file buffer size | ||
| 94 | st_buf_size equ 128 ;string arg. buffer size | ||
| 95 | fname_buf_size equ 64 ;file name buffer size | ||
| 96 | |||
| 97 | |||
| 98 | ;----- DOS EQUATES --------------------------------------------------; | ||
| 99 | std_in equ 0 ;STD input handle | ||
| 100 | std_out equ 1 ;STD output handle | ||
| 101 | std_err equ 2 ;STD error handle | ||
| 102 | dos_ent equ 21h ;DOS entry point | ||
| 103 | |||
| 104 | std_con_string_output equ 9 | ||
| 105 | get_version equ 48 | ||
| 106 | char_oper equ 55 ;get configuration parameters | ||
| 107 | open equ 61 ;DOS std open code | ||
| 108 | close equ 62 ;DOS std close code | ||
| 109 | read equ 63 ;DOS std read code | ||
| 110 | write equ 64 ;DOS std write code | ||
| 111 | lseek equ 66 ;DOS file seek | ||
| 112 | exit equ 76 ;DOS process exit code | ||
| 113 | |||
| 114 | |||
| 115 | ;----- Misc Data -----------------------------------------------; | ||
| 116 | make db "***MAUlloa/Microsoft/V12***" | ||
| 117 | rev db "8" | ||
| 118 | |||
| 119 | |||
| 120 | colon db ": " | ||
| 121 | n1_buf db "[" | ||
| 122 | n2_buf db 8 dup(0) ;buffer for number conversion | ||
| 123 | |||
| 124 | |||
| 125 | |||
| 126 | ;----- OPTION FLAGS -------------------------------------------------; | ||
| 127 | ; If a flag is set (0ffh) then the option has been selected, if | ||
| 128 | ;reset (0) then it has been not. All options are reset initially. | ||
| 129 | ; NOTE: the order of this table has to remain consistent with the | ||
| 130 | ;options dispatch code. If any changes are made they have to | ||
| 131 | ;correspond with the code. | ||
| 132 | |||
| 133 | opt_tbl: | ||
| 134 | |||
| 135 | v_flg db 0 | ||
| 136 | c_flg db 0 | ||
| 137 | n_flg db 0 | ||
| 138 | x_flg db 0 ;not used | ||
| 139 | l_flg db 0 ;not used | ||
| 140 | |||
| 141 | |||
| 142 | ;----- LINE COUNTERS ------------------------------------------------; | ||
| 143 | mtch_cntr dw 0 ;matched lines counter | ||
| 144 | line_cntr dw 0 ;line counter | ||
| 145 | |||
| 146 | |||
| 147 | ;----- MAIN ROUTINE -------------------------------------------------; | ||
| 148 | start: | ||
| 149 | |||
| 150 | ;----- CHECK VERSION NUMBER -----------------------------------------; | ||
| 151 | |||
| 152 | mov ah,get_version | ||
| 153 | int 21h | ||
| 154 | cmp al,2 | ||
| 155 | jge vers_ok | ||
| 156 | push cs | ||
| 157 | pop ds | ||
| 158 | mov dx,offset bad_vers | ||
| 159 | mov ah,std_con_string_output | ||
| 160 | int 21h | ||
| 161 | push es ;bad vers, exit a la 1.x | ||
| 162 | xor ax,ax | ||
| 163 | push ax | ||
| 164 | |||
| 165 | badfart proc far ;(what a hack!!) | ||
| 166 | ret | ||
| 167 | badfart endp | ||
| 168 | |||
| 169 | vers_ok: | ||
| 170 | |||
| 171 | push cs ;load ES to the right area, | ||
| 172 | pop es ; for use with DI register | ||
| 173 | |||
| 174 | assume es:code | ||
| 175 | |||
| 176 | ;--------------------------------------------------------------------; | ||
| 177 | |||
| 178 | mov si,81h ;Start addrss. of commad line buf. | ||
| 179 | |||
| 180 | call kill_bl ;Get rid of blanks | ||
| 181 | or bx,bx ;A CR found? | ||
| 182 | jz find_opt ;no, first find the options | ||
| 183 | args_missing: | ||
| 184 | mov dx,offset errmsg1 ;empty command line, no args: error. | ||
| 185 | mov cl,cs:errlen1 | ||
| 186 | call prt_err | ||
| 187 | mov al,2 ;error code for exit | ||
| 188 | jmp done | ||
| 189 | |||
| 190 | |||
| 191 | ;----- FIND THE OPTION IF ANY ---------------------------------------; | ||
| 192 | find_opt: | ||
| 193 | mov ah,char_oper ;get the dos switch char. | ||
| 194 | mov al,0 | ||
| 195 | int dos_ent ;switch char in DL | ||
| 196 | push dx | ||
| 197 | another_opt: | ||
| 198 | lodsb ;get the first char of command line | ||
| 199 | cmp al,' ' ;a blank? | ||
| 200 | je cont_scan | ||
| 201 | cmp al,CR ;a Carriage Return | ||
| 202 | je args_missing | ||
| 203 | pop dx ;get switch character | ||
| 204 | cmp al,dl ;is it the switch char? | ||
| 205 | jne find_str ;no, no options: get the string | ||
| 206 | push dx ;save for another round | ||
| 207 | |||
| 208 | lodsb ;get the option character | ||
| 209 | cmp al,' ' ;a blank? | ||
| 210 | je cont_scan ;yes, ignore and continue | ||
| 211 | cmp al,CR ;a CR? | ||
| 212 | je args_missing ;yes, error... | ||
| 213 | call make_caps ;Capitalize the character | ||
| 214 | mov bx,offset opt_tbl ;pointer to option flag table | ||
| 215 | |||
| 216 | cmp al,'V' ;the v option? | ||
| 217 | je opt_v | ||
| 218 | cmp al,'C' ;the c option? | ||
| 219 | je opt_c | ||
| 220 | cmp al,'N' ;the n option? | ||
| 221 | je opt_n | ||
| 222 | |||
| 223 | mov cs:errmsg5_opt,al ;save the option | ||
| 224 | mov dx,offset errmsg5 ;unknown option: error | ||
| 225 | mov cl,cs:errlen5 | ||
| 226 | call prt_err | ||
| 227 | mov dx,offset crlf ;print a CRLF | ||
| 228 | mov cx,2 | ||
| 229 | call prt_err | ||
| 230 | jmp another_opt ;process next option | ||
| 231 | |||
| 232 | opt_v: | ||
| 233 | mov di,0 | ||
| 234 | jmp short opt_dispatch | ||
| 235 | |||
| 236 | opt_c: | ||
| 237 | mov di,1 | ||
| 238 | jmp short opt_dispatch | ||
| 239 | |||
| 240 | opt_n: | ||
| 241 | mov di,2 | ||
| 242 | |||
| 243 | opt_dispatch: | ||
| 244 | mov es:byte ptr[bx+di],0ffh ;set the corresponding flag | ||
| 245 | jmp another_opt ;process the rest of the options | ||
| 246 | |||
| 247 | cont_scan: | ||
| 248 | dec si ;adjust SI | ||
| 249 | call kill_bl ;get rid of blanks | ||
| 250 | or bx,bx ;A CR found? | ||
| 251 | jz another_opt ;no, test for other options | ||
| 252 | jmp args_missing ;yes, error... | ||
| 253 | |||
| 254 | |||
| 255 | ;----- FIND STRING ARGUMENT -----------------------------------------; | ||
| 256 | find_str: | ||
| 257 | cmp al,quote_char ;string should start with a | ||
| 258 | jnz bad_str_err ; quote character, if not: error. | ||
| 259 | mov di,offset st_buffer ;String argument buffer addrss. | ||
| 260 | xor cx,cx ;Clear to keep string length. | ||
| 261 | |||
| 262 | move_str: | ||
| 263 | lodsb | ||
| 264 | cmp al,CR ;if a CR is found in the string | ||
| 265 | jnz str_ok ; then it's a bad string | ||
| 266 | bad_str_err: | ||
| 267 | mov dx,offset errmsg2 ;bad string error message | ||
| 268 | mov cl,cs:errlen2 | ||
| 269 | call prt_err ;print the error. | ||
| 270 | mov al,2 | ||
| 271 | jmp done | ||
| 272 | |||
| 273 | str_ok: | ||
| 274 | cmp al,quote_char ;look for a quote character | ||
| 275 | jnz move_char ;not an apost., move to buffer | ||
| 276 | lodsb ;an apost., check next char. | ||
| 277 | cmp al,quote_char ;another quote character? | ||
| 278 | je move_char ;yes, move it to the buffer | ||
| 279 | dec si ;no, adjust the pointer | ||
| 280 | mov es:st_length,cx ;store the string length | ||
| 281 | or cx,cx ;Is the string empty? | ||
| 282 | jnz other_args ;no: get the rest of the args. | ||
| 283 | mov al,1 ;empty: no matches(!?) | ||
| 284 | jmp done | ||
| 285 | move_char: | ||
| 286 | stosb ;put in buffer | ||
| 287 | inc cx ;increment string length | ||
| 288 | jmp move_str | ||
| 289 | |||
| 290 | |||
| 291 | ;----- FIND THE FILE ARGUMENTS --------------------------------------; | ||
| 292 | other_args: ;Process the rest of the command | ||
| 293 | ; line arguments. | ||
| 294 | call kill_bl ;get rid of leading blanks | ||
| 295 | or bx,bx ;At least one argument necessary, | ||
| 296 | jz further_args ; if a CR not found: ok. | ||
| 297 | |||
| 298 | ;----- USE STD IN FOR INPUT -----------------------------------------; | ||
| 299 | push cs | ||
| 300 | pop ds | ||
| 301 | mov ax,std_in ;handle | ||
| 302 | jmp fill | ||
| 303 | |||
| 304 | further_args: | ||
| 305 | call clr_cntrs ;set all counters to zero | ||
| 306 | mov di,offset file_name_buf ;Set pointer to the name buffer | ||
| 307 | xor cx,cx ;zero file name length | ||
| 308 | move_fname: | ||
| 309 | lodsb | ||
| 310 | cmp al,' ' ;A blank: end of file name, | ||
| 311 | je done_move | ||
| 312 | cmp al,CR ;A CR: idem. | ||
| 313 | je done_move | ||
| 314 | stosb ;store in name buffer | ||
| 315 | inc cx ;increment file name length | ||
| 316 | jmp move_fname | ||
| 317 | done_move: | ||
| 318 | dec si ;Adjust pointer for next round. | ||
| 319 | mov es:byte ptr[di],00h ;File names are null terminated | ||
| 320 | push si ;Save SI to continue com. line scan. | ||
| 321 | push ds ;Save DS register contents for | ||
| 322 | ; later because it points to the | ||
| 323 | ; rest of the arguments. | ||
| 324 | mov es:file_name_len,cx ;save the name length | ||
| 325 | |||
| 326 | ;----- OPEN FILE FOR READING ----------------------------------------; | ||
| 327 | push cs ;Load new DS with CS | ||
| 328 | pop ds | ||
| 329 | mov dx,offset file_name_buf ;addrss. of the file name | ||
| 330 | mov ah,open | ||
| 331 | mov al,0 ;file open for reading | ||
| 332 | int dos_ent ;call the DOS | ||
| 333 | jnc say_name ;if no carry then no errors | ||
| 334 | jmp open_error | ||
| 335 | |||
| 336 | ;----- PRINT FILE NAME ----------------------------------------------; | ||
| 337 | say_name: | ||
| 338 | push ax ;save file handle | ||
| 339 | mov dx,offset heading | ||
| 340 | mov cl,cs:heading_len | ||
| 341 | xor ch,ch | ||
| 342 | call prout | ||
| 343 | |||
| 344 | mov dx,offset file_name_buf | ||
| 345 | mov cx,ds:file_name_len | ||
| 346 | call prout | ||
| 347 | |||
| 348 | cmp ds:c_flg,0ffh ;count only flag set? | ||
| 349 | je xx1 | ||
| 350 | |||
| 351 | mov dx,offset crlf | ||
| 352 | mov cx,2 | ||
| 353 | call prout | ||
| 354 | |||
| 355 | xx1: | ||
| 356 | pop ax | ||
| 357 | |||
| 358 | ;----- Fill Buffer for Matching -------------------------------------; | ||
| 359 | fill: | ||
| 360 | mov bx,ax ;retrieve handle | ||
| 361 | refill: | ||
| 362 | mov dx,offset buffer ;data buffer addrss. | ||
| 363 | mov cx,buffer_size | ||
| 364 | mov ah,read | ||
| 365 | int dos_ent | ||
| 366 | jnc no_read_error ;if carry then read error | ||
| 367 | jmp read_error | ||
| 368 | no_read_error: | ||
| 369 | or ax,ax ;if ax=0 then all done | ||
| 370 | jnz go_match | ||
| 371 | cmp ds:c_flg,0ffh ;count only flag set? | ||
| 372 | jne sj2 | ||
| 373 | call print_count | ||
| 374 | sj2: | ||
| 375 | cmp bx,std_in ;Using STD IN? | ||
| 376 | jnz regular | ||
| 377 | jmp foo ;if so: all done, exit | ||
| 378 | regular: | ||
| 379 | mov ah,close ;otherwise close the file | ||
| 380 | int dos_ent | ||
| 381 | jmp scan_rest ;get another file | ||
| 382 | |||
| 383 | ;----- MATCH ROUTINE ------------------------------------------------; | ||
| 384 | ;Note: If input is being taken from a file the stack contains | ||
| 385 | ; (from top to bottom): | ||
| 386 | ; - Pointer to the next command in the command line | ||
| 387 | ; - Pointer to the program segment prefix (to be loaded into | ||
| 388 | ; DS to access the command line. | ||
| 389 | ; if the imput is from the standart input then NONE of it will be | ||
| 390 | ; in the stack. | ||
| 391 | |||
| 392 | go_match: | ||
| 393 | push bx ;save the file handle | ||
| 394 | mov bp,offset buffer ;ptr to first line of file | ||
| 395 | mov di,ax ;dispalcement from beg of buffer | ||
| 396 | |||
| 397 | cmp ax,buffer_size-1 ;last line of the file? | ||
| 398 | jg no_last_line ;if yes, add a CRLF just in case | ||
| 399 | mov bx,bp | ||
| 400 | cmp byte ptr[bx+di-1],LF ;finished with a LF? | ||
| 401 | je no_last_line ;yes, it's an OK line. | ||
| 402 | mov byte ptr[bx+di],CR ;put a CR at the end of the data | ||
| 403 | inc di | ||
| 404 | mov byte ptr[bx+di],LF ;put a LF ... | ||
| 405 | inc di | ||
| 406 | |||
| 407 | no_last_line: | ||
| 408 | push di ;save the # of chars. in the buffer | ||
| 409 | push bp | ||
| 410 | mov dx,ds:st_length ;length of the string arg. | ||
| 411 | dec dx ;adjust for later use | ||
| 412 | jmp short try_again | ||
| 413 | |||
| 414 | |||
| 415 | more_stuff_o: | ||
| 416 | jmp more_stuff | ||
| 417 | |||
| 418 | |||
| 419 | |||
| 420 | ;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------; | ||
| 421 | ;Note: at this point the stack contains (from top to bottom): | ||
| 422 | ; - Stuff mentioned before | ||
| 423 | ; - File Handle | ||
| 424 | ; - Number of chars. left in the buffer from the next line. | ||
| 425 | ; - Addrs. of the next line in the buffer. | ||
| 426 | ; | ||
| 427 | ; plus, DX has the adjusted length of the string argument. | ||
| 428 | |||
| 429 | try_again: | ||
| 430 | inc ds:line_cntr ;increment line counter | ||
| 431 | pop bp ;addrs. of next line in the buffer | ||
| 432 | mov di,bp ;points to beg. of a line | ||
| 433 | pop cx ;get # of chars left in the buffer | ||
| 434 | mov bx,cx ;save in case a non-complete line | ||
| 435 | mov al,LF ;search for a Line Feed | ||
| 436 | jcxz more_stuff_o ;no chars left in buffer | ||
| 437 | repnz scasb | ||
| 438 | jnz more_stuff_o ;no full line left in buffer | ||
| 439 | |||
| 440 | push cx ;save chars left in buffer | ||
| 441 | push di ;points to beg. of next line | ||
| 442 | mov cx,di | ||
| 443 | sub cx,bp ;length of the current line | ||
| 444 | mov bx,cx ;save in case it has a match | ||
| 445 | dec cx | ||
| 446 | dec cx ;CRLF characters discounted | ||
| 447 | jcxz try_again_opt ;if line empty go to next line | ||
| 448 | mov di,bp ;pointer to the beg. of current line | ||
| 449 | another_char: | ||
| 450 | ; | ||
| 451 | ; On entry: | ||
| 452 | ; BX line length | ||
| 453 | ; CX adjusted line length | ||
| 454 | ; DX adjusted string argument length | ||
| 455 | ; DI points to beg. of line | ||
| 456 | ; | ||
| 457 | |||
| 458 | IF KANJI | ||
| 459 | |||
| 460 | push dx ;save for next line | ||
| 461 | lop: | ||
| 462 | pop dx | ||
| 463 | push dx | ||
| 464 | inc dx ;different algorithm! | ||
| 465 | mov si,offset st_buffer ;pointer to beg. of string argument | ||
| 466 | |||
| 467 | comp_next_char: | ||
| 468 | push di | ||
| 469 | mov di,si | ||
| 470 | call is_prefix ;check for a prefix char | ||
| 471 | pop di | ||
| 472 | jnc nopre | ||
| 473 | lodsw | ||
| 474 | cmp cx,1 ; Can not compare a two byte char | ||
| 475 | jz try_again_opt1 ; if there is only one available | ||
| 476 | cmp ax,word ptr [di] | ||
| 477 | jz kmatch1 | ||
| 478 | call next_kchar ;no match, advance di to next kanji | ||
| 479 | jc try_again_opt1 ;not enough chars left in line | ||
| 480 | jmp short lop ;try another char in line | ||
| 481 | |||
| 482 | nopre: | ||
| 483 | lodsb | ||
| 484 | cmp al,byte ptr [di] | ||
| 485 | jz kmatch | ||
| 486 | call next_kchar ;no match, advance di to next kanji | ||
| 487 | jc try_again_opt1 ;not enough chars left in line | ||
| 488 | jmp short lop ;try another char in line | ||
| 489 | |||
| 490 | try_again_opt1: | ||
| 491 | pop dx | ||
| 492 | jmp try_again_opt | ||
| 493 | |||
| 494 | |||
| 495 | kmatch1: | ||
| 496 | dec dx ;last char had prefix so it was | ||
| 497 | ; long. | ||
| 498 | kmatch: | ||
| 499 | dec dx | ||
| 500 | jz a_matchk ; no chars left: a match! | ||
| 501 | call next_kchar | ||
| 502 | jc try_again_opt1 | ||
| 503 | jmp comp_next_char ; loop if chars left in arg. | ||
| 504 | |||
| 505 | a_matchk: | ||
| 506 | pop dx | ||
| 507 | |||
| 508 | ELSE | ||
| 509 | |||
| 510 | mov si,offset st_buffer ;pointer to beg. of string argument | ||
| 511 | lodsb ;get first character of the str. arg. | ||
| 512 | repnz scasb ;search for a match in current line | ||
| 513 | jnz try_again_opt ;no match, try the next line | ||
| 514 | cmp cx,dx ;compare lengths, a full match is not | ||
| 515 | jb try_again_opt ; possible if CX < DX. | ||
| 516 | push di ;save addrs. of next char. in the line | ||
| 517 | push cx ;save the # of chars. left in the line | ||
| 518 | mov cx,dx ;get the adjusted string arg. length | ||
| 519 | jcxz a_match ;if a single char string, then match! | ||
| 520 | repz cmpsb ;compare string with line | ||
| 521 | jz a_match ;a match found, hurrah! | ||
| 522 | pop cx ;no match, get # of chars remaining | ||
| 523 | ; in the line. | ||
| 524 | pop di ;position of the next char. in the line | ||
| 525 | jmp another_char | ||
| 526 | |||
| 527 | |||
| 528 | ;----- A MATCH: CHECK FOR THE v OPTION ------------------------------; | ||
| 529 | a_match: | ||
| 530 | pop ax ;adjust stack | ||
| 531 | pop ax | ||
| 532 | ENDIF | ||
| 533 | |||
| 534 | cmp ds:v_flg,0ffh ;is flag set? | ||
| 535 | jne prt_line ;no, print the line | ||
| 536 | jmp try_again | ||
| 537 | |||
| 538 | ;----- NO MATCH: CHECK FOR THE v OPTION -----------------------------; | ||
| 539 | try_again_opt: | ||
| 540 | cmp ds:v_flg,0ffh ;is flag set? | ||
| 541 | jne try_again ;no goto next line | ||
| 542 | |||
| 543 | ;----- PRINT THE LINE WITH THE MATCH --------------------------------; | ||
| 544 | ;Note: at this point the stack contains (top to bottom) | ||
| 545 | ; - Stuff mentioned before | ||
| 546 | ; | ||
| 547 | ; plus, BP points to begginig of the current line, BX has the length | ||
| 548 | ;of the current line including the CRLF, and DX the adjusted length of | ||
| 549 | ;the string argument. | ||
| 550 | |||
| 551 | prt_line: | ||
| 552 | cmp ds:c_flg,0ffh ;is count only flag set? | ||
| 553 | jne no_c_flg | ||
| 554 | inc ds:mtch_cntr ;yes, increment counter | ||
| 555 | jmp try_again | ||
| 556 | |||
| 557 | no_c_flg: | ||
| 558 | push dx ;save the adjusted string arg. length | ||
| 559 | cmp ds:n_flg,0ffh ;is line number flag set? | ||
| 560 | jne no_n_flg | ||
| 561 | call prt_lcntr | ||
| 562 | no_n_flg: | ||
| 563 | mov dx,bp | ||
| 564 | mov cx,bx | ||
| 565 | call prout | ||
| 566 | pop dx ;restore | ||
| 567 | jmp try_again | ||
| 568 | |||
| 569 | ;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------; | ||
| 570 | ; The scanning routines have detected that the buffer does not | ||
| 571 | ;contain a full line any more. More lines have to be read into the | ||
| 572 | ;buffer. But first perform a seek on the file in order to re-read | ||
| 573 | ;the non-complete line into the begining of the buffer. | ||
| 574 | ; Uppon entry BP contains points to the begining of the non-complete | ||
| 575 | ;line, and BX has the number of characters left in the buffer. | ||
| 576 | ; The Stack contains (top to bottom): | ||
| 577 | ; - Pointer to the next command in the command line | ||
| 578 | ; - Pointer to the program segment prefix (to be loaded into | ||
| 579 | ; DS to access the command line). | ||
| 580 | ; - File handle. | ||
| 581 | |||
| 582 | more_stuff: | ||
| 583 | mov dx,bx ;get chars left in buffer | ||
| 584 | pop bx ;get the handle | ||
| 585 | or dx,dx ;are there 0 left? | ||
| 586 | jz no_seek ;yes, do not seek | ||
| 587 | neg dx ;form two's complement | ||
| 588 | mov cx,-1 | ||
| 589 | mov al,1 ;seek from the current position | ||
| 590 | mov ah,lseek ;seek on file | ||
| 591 | int dos_ent | ||
| 592 | jc read_error | ||
| 593 | no_seek: | ||
| 594 | jmp refill ;no errors: refill the buffer | ||
| 595 | read_error: | ||
| 596 | cmp bx,std_in ;Using STD IN? | ||
| 597 | je foo ;if so: all done, exit | ||
| 598 | mov ah,close ;close the file | ||
| 599 | int dos_ent | ||
| 600 | mov dx,offset errmsg4_pre ;read error | ||
| 601 | mov cl,cs:errlen4_pre | ||
| 602 | call prt_file_name ;print the file name in error | ||
| 603 | mov dx,offset errmsg4_post ;read error | ||
| 604 | mov cl,cs:errlen4_post | ||
| 605 | jmp r_error | ||
| 606 | |||
| 607 | ;----- PRINT ERRORS -------------------------------------------------; | ||
| 608 | open_error: | ||
| 609 | mov dx,offset errmsg3_pre ;error in open operation | ||
| 610 | mov cl,cs:errlen3_pre | ||
| 611 | call prt_err_2 ;print error message | ||
| 612 | call prt_file_name ;print the file name in error | ||
| 613 | mov dx,offset errmsg3_post ;error in open operation | ||
| 614 | mov cl,cs:errlen3_post | ||
| 615 | r_error: | ||
| 616 | call prt_err_2 ;print error message | ||
| 617 | |||
| 618 | ;----- SCAN THE REST OF THE COMMAND LINE ----------------------------; | ||
| 619 | scan_rest: | ||
| 620 | pop ds ;restore pointer to comm. line | ||
| 621 | pop si ;restore pointer to next comm. | ||
| 622 | call kill_bl ;look for further args. | ||
| 623 | or bx,bx ;test for a CR | ||
| 624 | jnz foo | ||
| 625 | jmp further_args | ||
| 626 | foo: | ||
| 627 | mov al,0 ;Proper code | ||
| 628 | done: | ||
| 629 | mov ah,exit ;All done, exit with proper code. | ||
| 630 | int dos_ent | ||
| 631 | |||
| 632 | |||
| 633 | ;--------------------------------------------------------------------; | ||
| 634 | ; Get rid of blanks in command line. ; | ||
| 635 | ; Advances the SI reg till the next non-blank character, if the ; | ||
| 636 | ; character is a CR (0dh) then returns with BX non-zero, otherwise ; | ||
| 637 | ; BX is zero. ; | ||
| 638 | ; ; | ||
| 639 | ; entry: ; | ||
| 640 | ; SI points to the first character on the line to scan. ; | ||
| 641 | ; ; | ||
| 642 | ; exit: ; | ||
| 643 | ; SI points to the first non-blank character found. ; | ||
| 644 | ; BX contains 0D hex if the first non-blank found is ; | ||
| 645 | ; a Carriage Return, otherwise it is 0. ; | ||
| 646 | ; ; | ||
| 647 | ; modifies: ; | ||
| 648 | ; BX, SI, and AX ; | ||
| 649 | ; ; | ||
| 650 | ;--------------------------------------------------------------------; | ||
| 651 | kill_bl: | ||
| 652 | cld ;increment | ||
| 653 | xor bx,bx ;zero bx to start: no CR found | ||
| 654 | no_bl: | ||
| 655 | lodsb ;get rid of blanks | ||
| 656 | cmp al,' ' | ||
| 657 | je no_bl | ||
| 658 | cmp al,CR | ||
| 659 | jnz no_cr | ||
| 660 | mov bx,ax ;make bx non-zero (actually 0dh) | ||
| 661 | no_cr: | ||
| 662 | dec si ;adjust pointer | ||
| 663 | ret | ||
| 664 | |||
| 665 | |||
| 666 | ;--------------------------------------------------------------------; | ||
| 667 | ; Clear Counters ; | ||
| 668 | ;--------------------------------------------------------------------; | ||
| 669 | clr_cntrs: | ||
| 670 | mov byte ptr es:mtch_cntr,0 | ||
| 671 | mov byte ptr es:line_cntr,0 | ||
| 672 | ret | ||
| 673 | |||
| 674 | ;--------------------------------------------------------------------; | ||
| 675 | ; Print Count of Matched lines ; | ||
| 676 | ; ; | ||
| 677 | ; Modifies: AX,CX,DX and DI ; | ||
| 678 | ;--------------------------------------------------------------------; | ||
| 679 | print_count: | ||
| 680 | push bx ;save handle | ||
| 681 | cmp bx,std_in ;using std_in? | ||
| 682 | jz sj3 ;if so do not print file name | ||
| 683 | |||
| 684 | mov dx,offset colon | ||
| 685 | mov cx,2 | ||
| 686 | call prout ;print colon | ||
| 687 | sj3: | ||
| 688 | mov ax,ds:mtch_cntr | ||
| 689 | mov di,offset n2_buf ;buffer for characters | ||
| 690 | call bin2asc ;convert to ascii | ||
| 691 | mov dx,offset n2_buf | ||
| 692 | call prout ;print the number | ||
| 693 | mov dx,offset crlf | ||
| 694 | mov cx,2 | ||
| 695 | call prout ;print an end of line | ||
| 696 | pop bx | ||
| 697 | ret | ||
| 698 | |||
| 699 | |||
| 700 | ;--------------------------------------------------------------------; | ||
| 701 | ; Print relative line number ; | ||
| 702 | ; ; | ||
| 703 | ; Modifies: AX,CX and DI ; | ||
| 704 | ;--------------------------------------------------------------------; | ||
| 705 | prt_lcntr: | ||
| 706 | push bx | ||
| 707 | push dx | ||
| 708 | mov ax,ds:line_cntr | ||
| 709 | mov di,offset n2_buf | ||
| 710 | call bin2asc | ||
| 711 | mov byte ptr[di],"]" | ||
| 712 | inc cx | ||
| 713 | inc cx | ||
| 714 | mov dx,offset n1_buf | ||
| 715 | call prout | ||
| 716 | pop dx | ||
| 717 | pop bx | ||
| 718 | ret | ||
| 719 | |||
| 720 | ;--------------------------------------------------------------------; | ||
| 721 | ; Print string to STD_OUT ; | ||
| 722 | ;--------------------------------------------------------------------; | ||
| 723 | prout: | ||
| 724 | mov bx,std_out | ||
| 725 | mov ah,write | ||
| 726 | int dos_ent | ||
| 727 | ret | ||
| 728 | |||
| 729 | |||
| 730 | ;--------------------------------------------------------------------; | ||
| 731 | ; Binary to Ascii conversion routine ; | ||
| 732 | ; ; | ||
| 733 | ; Entry: ; | ||
| 734 | ; AX Binary number ; | ||
| 735 | ; DI Points to one past the last char in the ; | ||
| 736 | ; result buffer. ; | ||
| 737 | ; ; | ||
| 738 | ; Exit: ; | ||
| 739 | ; Result in the buffer MSD first ; | ||
| 740 | ; CX Digit count ; | ||
| 741 | ; ; | ||
| 742 | ; Modifies: ; | ||
| 743 | ; AX,BX,CX,DX and DI ; | ||
| 744 | ; ; | ||
| 745 | ;--------------------------------------------------------------------; | ||
| 746 | bin2asc: | ||
| 747 | mov bx,0ah | ||
| 748 | xor cx,cx | ||
| 749 | go_div: | ||
| 750 | inc cx | ||
| 751 | cmp ax,bx | ||
| 752 | jb div_done | ||
| 753 | xor dx,dx | ||
| 754 | div bx | ||
| 755 | add dl,'0' ;convert to ASCII | ||
| 756 | push dx | ||
| 757 | jmp short go_div | ||
| 758 | |||
| 759 | div_done: | ||
| 760 | add al,'0' | ||
| 761 | push ax | ||
| 762 | mov bx,cx | ||
| 763 | deposit: | ||
| 764 | pop ax | ||
| 765 | stosb | ||
| 766 | loop deposit | ||
| 767 | mov cx,bx | ||
| 768 | ret | ||
| 769 | |||
| 770 | |||
| 771 | ;--------------------------------------------------------------------; | ||
| 772 | ; Print the current file name ; | ||
| 773 | ; ; | ||
| 774 | ; modifies: ; | ||
| 775 | ; DX, CX, BX and AX ; | ||
| 776 | ;--------------------------------------------------------------------; | ||
| 777 | prt_file_name: | ||
| 778 | mov dx,offset file_name_buf ;print the file name | ||
| 779 | mov cx,ds:file_name_len ;retrive file name length | ||
| 780 | jmp short prt_err_2 | ||
| 781 | |||
| 782 | |||
| 783 | ;--------------------------------------------------------------------; | ||
| 784 | ; Print an error message to the Standart error ; | ||
| 785 | ; ; | ||
| 786 | ; entry: ; | ||
| 787 | ; DX has the pointer to the message ; | ||
| 788 | ; CX has the length of the message ; | ||
| 789 | ; ; | ||
| 790 | ; modifies: ; | ||
| 791 | ; BX and AX ; | ||
| 792 | ;--------------------------------------------------------------------; | ||
| 793 | prt_err: | ||
| 794 | push ds ;Save the current DS | ||
| 795 | push cs ;Make DS point to the right | ||
| 796 | pop ds ; place, for DOS use. | ||
| 797 | call prt_err_2 | ||
| 798 | pop ds | ||
| 799 | ret | ||
| 800 | |||
| 801 | prt_err_2: | ||
| 802 | xor ch,ch | ||
| 803 | mov bx,std_err | ||
| 804 | mov ah,write | ||
| 805 | int dos_ent ;write error message | ||
| 806 | ret | ||
| 807 | |||
| 808 | |||
| 809 | ;--------------------------------------------------------------------; | ||
| 810 | ; CAPIALIZES THE CHARACTER IN AL ; | ||
| 811 | ; ; | ||
| 812 | ; entry: ; | ||
| 813 | ; AL has the character to Capitalize ; | ||
| 814 | ; ; | ||
| 815 | ; exit: ; | ||
| 816 | ; AL has the capitalized character ; | ||
| 817 | ; ; | ||
| 818 | ; modifies: ; | ||
| 819 | ; AL ; | ||
| 820 | ;--------------------------------------------------------------------; | ||
| 821 | make_caps: | ||
| 822 | cmp al,'a' | ||
| 823 | jb no_cap | ||
| 824 | cmp al,'z' | ||
| 825 | jg no_cap | ||
| 826 | and al,0dfh | ||
| 827 | no_cap: | ||
| 828 | ret | ||
| 829 | |||
| 830 | |||
| 831 | |||
| 832 | IF KANJI | ||
| 833 | |||
| 834 | ;--------------------------------------------------------------------; | ||
| 835 | ; ADVANCE POINTER TO NEXT KANJI CHARACTER ; | ||
| 836 | ; ; | ||
| 837 | ; entry: DI points to a Kanji string ; | ||
| 838 | ; CX length in bytes of the string ; | ||
| 839 | ; ; | ||
| 840 | ; exit: DI points to next Kanji char ; | ||
| 841 | ; CX has number of bytes left ; | ||
| 842 | ; ; | ||
| 843 | ; modifies: AX ; | ||
| 844 | ; ; | ||
| 845 | ;--------------------------------------------------------------------; | ||
| 846 | next_kchar: | ||
| 847 | jcxz no_kleft | ||
| 848 | call is_prefix | ||
| 849 | jnc no_p | ||
| 850 | inc di | ||
| 851 | dec cx | ||
| 852 | jcxz no_kleft ; for insurance | ||
| 853 | no_p: | ||
| 854 | inc di | ||
| 855 | dec cx | ||
| 856 | clc | ||
| 857 | ret | ||
| 858 | |||
| 859 | no_kleft: | ||
| 860 | stc | ||
| 861 | ret | ||
| 862 | |||
| 863 | |||
| 864 | ;--------------------------------------------------------------------; | ||
| 865 | ; FIND OUT IS THE BYTE IS A KANJI PREFIX ; | ||
| 866 | ; ; | ||
| 867 | ; entry: DI points to a kanji string ; | ||
| 868 | ; ; | ||
| 869 | ; exit: Carry set if it is a kanji prefix ; | ||
| 870 | ; ; | ||
| 871 | ; modifies: AX ; | ||
| 872 | ; ; | ||
| 873 | ;--------------------------------------------------------------------; | ||
| 874 | is_prefix: | ||
| 875 | mov al,byte ptr [di] | ||
| 876 | cmp al,81h | ||
| 877 | jb nok | ||
| 878 | cmp al,0a0h | ||
| 879 | jb isk | ||
| 880 | cmp al,0e0h | ||
| 881 | jb nok | ||
| 882 | cmp al,0fdh | ||
| 883 | jb isk | ||
| 884 | nok: | ||
| 885 | clc | ||
| 886 | ret | ||
| 887 | isk: | ||
| 888 | stc | ||
| 889 | ret | ||
| 890 | |||
| 891 | ENDIF | ||
| 892 | |||
| 893 | |||
| 894 | ;----- PATCH AREA ---------------------------------------------------; | ||
| 895 | |||
| 896 | patch_area dw 100h dup(?) | ||
| 897 | |||
| 898 | |||
| 899 | |||
| 900 | ;----- BUFFER AREA --------------------------------------------------; | ||
| 901 | st_length dw 0 ;String argumnet length | ||
| 902 | st_buffer db st_buf_size dup(?) ;String argument buffer | ||
| 903 | |||
| 904 | file_name_len dw 0 ;File name length | ||
| 905 | file_name_buf db fname_buf_size+1 dup(?) ;File name buffer,(allow for | ||
| 906 | ; null at the end). | ||
| 907 | |||
| 908 | buffer db buffer_size+1 dup(?) ;file buffer, the last byte is | ||
| 909 | ;a guard in case of forced insertion | ||
| 910 | ;of a CRLF pair. | ||
| 911 | |||
| 912 | ;----- ERROR MESSAGES -----------------------------------------------; | ||
| 913 | EXTRN bad_vers:byte,crlf:byte,errmsg1:byte,errlen1:byte,errmsg2:byte | ||
| 914 | EXTRN errmsg3_pre:byte,errlen3_pre:byte | ||
| 915 | EXTRN errmsg3_post:byte,errlen3_post:byte | ||
| 916 | EXTRN errmsg4_pre:byte,errlen4_pre:byte | ||
| 917 | EXTRN errmsg4_post:byte,errlen4_post:byte | ||
| 918 | EXTRN heading:byte,heading_len:byte,errlen2:byte | ||
| 919 | EXTRN errmsg5:byte,errmsg5_opt:byte,errlen5:byte | ||
| 920 | code ends | ||
| 921 | |||
| 922 | |||
| 923 | ;----- STACK AREA ---------------------------------------------------; | ||
| 924 | stack segment stack | ||
| 925 | |||
| 926 | dw 64 dup(?,?) | ||
| 927 | stack_top equ $ | ||
| 928 | |||
| 929 | stack ends | ||
| 930 | |||
| 931 | end start | ||
| 932 | |||