|
|
1.1 ! root 1: name cpgrepsub ! 2: ! 3: retlen equ 2 ; Size of return address on stack ! 4: ! 5: dgroup group _data ! 6: ! 7: extrn _casesen: word ; Case-sensitivity flag ! 8: extrn _stringlist: word ; Table of string lists ! 9: extrn _target: byte ; Target string ! 10: extrn _targetlen: word ; Length of target string ! 11: extrn _transtab: byte ; Translation table for _findlist ! 12: ! 13: ; This segment is puposely word-aligned. See note ! 14: ; in _findlist below. ! 15: ! 16: _text segment word public 'code' ! 17: assume cs:_text, ds:dgroup, es:nothing, ss:dgroup ! 18: ! 19: ; char *findone(buffer,bufend) ! 20: ; char *buffer /* Buffer in which to search */ ! 21: ; char *bufend; /* End of buffer */ ! 22: ; ! 23: ; NOTE: targetlen MUST BE greater than zero ! 24: ! 25: buffer equ word ptr [bp+retlen+2] ! 26: bufend equ word ptr [bp+retlen+4] ! 27: ! 28: EVEN ! 29: ! 30: public _findone ! 31: _findone proc near ! 32: push bp ! 33: mov bp,sp ! 34: push di ! 35: push si ! 36: push es ! 37: push ds ; ES = DS ! 38: pop es ! 39: mov cx,bufend ; CX = end of buffer ! 40: mov di,buffer ; ES:DI = buffer ! 41: sub cx,di ; CX = length of buffer ! 42: jbe sfnomatch ; length less than or equal to zero ! 43: mov dx,_targetlen ; DX = length of target ! 44: dec dx ; Decrement it ! 45: sub cx,dx ; target must fit in buffer ! 46: jbe sfnomatch ; (no match if buffer too short) ! 47: ! 48: ; CX = buffer length ! 49: ; DX = target length (minus first character) ! 50: ; ES:DI = buffer pointer ! 51: ! 52: sf0: jcxz sfnomatch ; No match if count zero ! 53: mov si,offset dgroup:_target ; DS:SI = target ! 54: lodsb ; AL = first byte of target ! 55: repne scasb ; Look for first character ! 56: jne sfnomatch ; jump if not found ! 57: mov bx,cx ; BX = buffer length ! 58: mov ax,di ; AX = buffer pointer ! 59: mov cx,dx ; Get count for cmpsb ! 60: or cx,cx ; Zero? (JCXZ doesn't set flag) ! 61: je sf1 ; yes, skip compare ! 62: repe cmpsb ; Do string compare ! 63: sf1: mov di,ax ; DI = buffer pointer ! 64: mov cx,bx ; CX = buffer length ! 65: jne sf0 ; Loop if no match ! 66: dec ax ; AX = offset of start of match ! 67: jmp short sf4 ! 68: ! 69: sfnomatch: ! 70: xor ax,ax ; No match ! 71: sf4: pop es ! 72: pop si ! 73: pop di ! 74: pop bp ! 75: ret ! 76: _findone endp ! 77: ! 78: ! 79: ; int revfind(s,c,slen) ! 80: ; char *s; /* String to search */ ! 81: ; int c; /* Char to search for */ ! 82: ; int slen; /* Length of s */ ! 83: ! 84: s equ [bp+retlen+2] ! 85: c equ [bp+retlen+4] ! 86: slen equ [bp+retlen+6] ! 87: ! 88: EVEN ! 89: ! 90: public _revfind ! 91: _revfind proc near ! 92: push bp ! 93: mov bp,sp ! 94: push di ! 95: push es ! 96: push ds ! 97: pop es ! 98: mov di,s ! 99: mov ax,c ! 100: mov cx,slen ! 101: jcxz rf1 ! 102: std ! 103: repne scasb ! 104: cld ! 105: mov cx,s ! 106: jne rf0 ! 107: inc di ! 108: rf0: sub cx,di ! 109: rf1: mov ax,cx ! 110: pop es ! 111: pop di ! 112: pop bp ! 113: ret ! 114: _revfind endp ! 115: ! 116: ! 117: ; int countlines(start,finish) ! 118: ; char *start; ! 119: ; char *finish; ! 120: ! 121: start equ [bp+retlen+2] ! 122: finish equ [bp+retlen+4] ! 123: ! 124: EVEN ! 125: ! 126: public _countlines ! 127: _countlines proc near ! 128: push bp ! 129: mov bp,sp ! 130: push di ! 131: push es ! 132: push ds ! 133: pop es ! 134: xor dx,dx ; Accumulate count in DX ! 135: mov di,start ; ES:DI points to start ! 136: mov cx,finish ; Put length in CX ! 137: sub cx,di ! 138: jbe cl1 ; branch if no bytes ! 139: mov al,0Ah ; Search for linefeeds ! 140: cl0: jcxz cl1 ; Exit loop if count zero ! 141: repne scasb ; Do search ! 142: jne cl1 ; branch if none found ! 143: inc dx ; Increment count ! 144: jmp short cl0 ; Loop ! 145: cl1: mov ax,dx ; Return line count in AX ! 146: pop es ! 147: pop di ! 148: pop bp ! 149: ret ! 150: _countlines endp ! 151: ! 152: ! 153: ; char *findlist(buffer,bufend) ! 154: ; char *buffer; /* Buffer to search */ ! 155: ; char *bufend; /* End of buffer */ ! 156: ! 157: savesi equ word ptr [bp-2] ! 158: endbyte equ byte ptr [bp-4] ! 159: ! 160: stringnode struc ! 161: s_alt dw ? ; List of alternate portions ! 162: s_suf dw ? ; Pointer to suffix string list ! 163: s_must dw ? ; Length of portion that must match ! 164: stringnode ends ! 165: ! 166: EVEN ! 167: ! 168: flworker dw findsubi, findsub ; Worker dispatch table ! 169: ! 170: public _findlist ! 171: _findlist proc near ! 172: ASSUME DS:DGROUP, ES:NOTHING, SS:DGROUP ! 173: ! 174: push bp ! 175: mov bp,sp ! 176: sub sp,4 ; Make room for local vars ! 177: push di ! 178: push si ! 179: push ds ! 180: pop es ! 181: ASSUME ES:DGROUP ! 182: ! 183: ; We mark the end of our search buffer with 0FFh so that ! 184: ; any comparisons that might run past the end of the buffer ! 185: ; will fail on the 0FFh. We choose 0FFh so that if the ! 186: ; comparison fails on it, it will always appear as though ! 187: ; the string in the buffer is greater that the string in ! 188: ; the search list. This will prevent us from stopping ! 189: ; the search too soon. Of course, we must restore the byte ! 190: ; when we're done. ! 191: ! 192: mov bx,bufend ; BX = end of buffer ! 193: mov al,0FFh ; End marker ! 194: xchg byte ptr [bx],al ; AL = byte after end of buffer ! 195: mov endbyte,al ; Save the byte ! 196: ! 197: mov cx,bx ; CX = end of buffer ! 198: mov si,buffer ; SI = buffer ! 199: sub cx,si ; CX = buffer length ! 200: jbe fl1 ; no match if empty buffer ! 201: mov bx,offset dgroup:_transtab ; BX = translation table address ! 202: ! 203: mov di,_casesen ; Get flag ! 204: shl di,1 ; Scale to word index ! 205: call cs:flworker[di] ; Call helper ! 206: jc fl1 ; branch if no match ! 207: ! 208: ; We have a match ! 209: ; ! 210: ; SI = offset of first character past end of matched string ! 211: ; savesi = offset of first character past start of matched string ! 212: ! 213: mov ax,savesi ; AX = 1st char past start ! 214: dec ax ; AX = start of matched string ! 215: jmp short fl2 ! 216: ! 217: ; We did not find a match ! 218: ! 219: fl1: ! 220: xor ax,ax ; Return NULL ! 221: ! 222: ; Restore end byte before leaving ! 223: ! 224: fl2: ! 225: mov bx,bufend ; BX = end of buffer ! 226: mov dl,endbyte ; DL = end byte ! 227: mov [bx],dl ; Restore byte ! 228: ! 229: pop si ! 230: pop di ! 231: mov sp,bp ! 232: pop bp ! 233: ret ! 234: ! 235: _findlist endp ! 236: ! 237: ! 238: ;*** findsub - case-sensitive worker for _findlist ! 239: ; ! 240: ; This function does most of the work for ! 241: ; case-sensitive multi-string searches. ! 242: ; ! 243: ; ENTRY BX = address of translation table ! 244: ; CX = number of bytes left in buffer ! 245: ; DS:SI = buffer pointer ! 246: ; SS:BP = pointer to stack frame for _findlist ! 247: ; EXIT Carry set ! 248: ; No match ! 249: ; Carry clear ! 250: ; DS:SI = pointer to first character after match ! 251: ; USES AX, CX, DX, DI, SI, Flags ! 252: ! 253: EVEN ! 254: ! 255: public findsub, fs0, fs1, fs2, fs3, fs4, fs5, fs6 ! 256: findsub proc near ! 257: ASSUME DS:DGROUP, ES:DGROUP, SS:DGROUP ! 258: ! 259: fs0: ! 260: xor ax,ax ; AH = 0 ! 261: ! 262: ; AH = 0 ! 263: ; BX = address of translation table ! 264: ; CX = number of bytes left in buffer ! 265: ; SI = buffer pointer ! 266: ; DS = ES = SS = DGROUP ! 267: ! 268: fs1: ! 269: lodsb ; Character in AL ! 270: xlat byte ptr [bx] ; Translate character to index ! 271: or al,al ; Zero means invalid 1st byte ! 272: loopz fs1 ; if so, try next character ! 273: ! 274: ; Either the zero bit is set, meaning the buffer is empty, ! 275: ; or the zero bit is clear, meaning we have a valid first ! 276: ; character. Either way, CX has been decremented. ! 277: ! 278: jz fs6 ; branch if buffer empty ! 279: mov savesi,si ; Save buffer pointer ! 280: shl ax,1 ; Scale to word index ! 281: mov di,ax ! 282: mov di,_stringlist[di] ; DI points to string record ! 283: or di,di ; One byte match? (OR clears carry) ! 284: jz fs3 ; yes, skip ahead ! 285: ! 286: ; Loop to search for match. ! 287: ; BX = address of translation table ! 288: ; DI = pointer to string record ! 289: ; SI = pointer into buffer ! 290: ! 291: fs2: ! 292: mov cx,[di].s_must ; CX = length of string ! 293: sub di,cx ; DI = pointer to string ! 294: mov dx,si ; Save pointer to start of suffix ! 295: repe cmpsb ; Strings match? ! 296: ja fs4 ; no, try alternate if follows ! 297: jb fs5 ; no, cannot be in this list ! 298: add di,cx ; DI = pointer to string record ! 299: mov di,[di].s_suf ; Get pointer to suffix string list ! 300: or di,di ; Is there one? (OR clears carry) ! 301: jnz fs2 ; yes, keep looking ! 302: ! 303: ; Match found ! 304: ! 305: fs3: ! 306: ret ; no, we have a match ! 307: ! 308: ; Try alternate suffix ! 309: ! 310: fs4: ! 311: add di,cx ; DI = pointer to string record ! 312: mov di,[di].s_alt ; Get pointer to alternate ! 313: mov si,dx ; Restore SI to start of suffix ! 314: or di,di ; Is there one? ! 315: jnz fs2 ; yes, loop ! 316: ! 317: ; Try new first character ! 318: ! 319: fs5: ! 320: mov cx,bufend ; CX = end of buffer ! 321: mov si,savesi ; Restore SI to saved value ! 322: sub cx,si ; CX = length of buffer ! 323: ja short fs0 ; Try next character in buffer ! 324: ! 325: ; No match ! 326: ! 327: fs6: ! 328: stc ; No match ! 329: ret ! 330: ! 331: findsub endp ! 332: ! 333: ! 334: ;*** findsubi - case-insensitive worker for _findlist ! 335: ; ! 336: ; This function does most of the work for ! 337: ; case-insensitive multi-string searches. ! 338: ; ! 339: ; ENTRY BX = address of translation table ! 340: ; CX = number of bytes left in buffer ! 341: ; DS:SI = buffer pointer ! 342: ; SS:BP = pointer to stack frame for _findlist ! 343: ; EXIT Carry set ! 344: ; No match ! 345: ; Carry clear ! 346: ; DS:SI = pointer to first character after match ! 347: ; USES AX, CX, DX, DI, SI, Flags ! 348: ! 349: EVEN ! 350: ! 351: public findsubi ! 352: findsubi proc near ! 353: ASSUME DS:DGROUP, ES:DGROUP, SS:DGROUP ! 354: ! 355: fsi0: ! 356: xor ax,ax ; AH = 0 ! 357: ! 358: ; AH = 0 ! 359: ; BX = address of translation table ! 360: ; CX = number of bytes left in buffer ! 361: ; SI = buffer pointer ! 362: ; DS = ES = SS = DGROUP ! 363: ! 364: fsi1: ! 365: lodsb ; Character in AL ! 366: xlat byte ptr [bx] ; Translate character to index ! 367: or al,al ; Zero means invalid 1st byte ! 368: loopz fsi1 ; if so, try next character ! 369: ! 370: ; Either the zero bit is set, meaning the buffer is empty, ! 371: ; or the zero bit is clear, meaning we have a valid first ! 372: ; character. Either way, CX has been decremented. ! 373: ! 374: jz fsi7 ; branch if buffer empty ! 375: mov savesi,si ; Save buffer pointer ! 376: shl ax,1 ; Scale to word index ! 377: mov di,ax ! 378: mov di,_stringlist[di] ; DI points to string record ! 379: or di,di ; One byte match? (OR clears carry) ! 380: jz fsi4 ; yes, skip ahead ! 381: ! 382: ; Loop to search for match. ! 383: ; BX = address of translation table ! 384: ; DI = pointer to string record ! 385: ; SI = pointer into buffer ! 386: ! 387: fsi2: ! 388: mov cx,[di].s_must ; CX = length of string ! 389: sub di,cx ; DI = pointer to string ! 390: mov dx,si ; Save pointer to start of suffix ! 391: fsi3: lodsb ; Byte in AL, SI = SI + 1 ! 392: mov ah,[di] ; Byte in AH, DI = DI + 1 ! 393: inc di ! 394: or ax,2020h ; Fold bytes onto lower case ! 395: cmp al,ah ; Compare bytes ! 396: loope fsi3 ; Loop while same ! 397: ja fsi5 ; no, try alternate if follows ! 398: jb fsi6 ; no, cannot be in this list ! 399: add di,cx ; DI = pointer to string record ! 400: mov di,[di].s_suf ; Get pointer to suffix string list ! 401: or di,di ; Is there one? (OR clears carry) ! 402: jnz fsi2 ; yes, keep looking ! 403: ! 404: ; Match found ! 405: ! 406: fsi4: ! 407: ret ; no, we have a match ! 408: ! 409: ; Try alternate suffix ! 410: ! 411: fsi5: ! 412: add di,cx ; DI = pointer to string record ! 413: mov di,[di].s_alt ; Get pointer to alternate ! 414: mov si,dx ; Restore SI to start of suffix ! 415: or di,di ; Is there one? ! 416: jnz fsi2 ; yes, loop ! 417: ! 418: ; Try new first character ! 419: ! 420: fsi6: ! 421: mov cx,bufend ; CX = end of buffer ! 422: mov si,savesi ; Restore SI to saved value ! 423: sub cx,si ; CX = length of buffer ! 424: ja short fsi0 ; Try next character in buffer ! 425: ! 426: ; No match ! 427: ! 428: fsi7: ! 429: stc ; No match ! 430: ret ! 431: ! 432: findsubi endp ! 433: ! 434: ! 435: ; int strnspn(s,t,n) ! 436: ; char *s; /* String to search */ ! 437: ; char *t; /* Target list */ ! 438: ; int n; /* Length of s */ ! 439: ! 440: s equ word ptr [bp+retlen+2] ! 441: t equ word ptr [bp+retlen+4] ! 442: n equ word ptr [bp+retlen+6] ! 443: ! 444: EVEN ! 445: ! 446: public _strnspn ! 447: _strnspn proc near ! 448: push bp ! 449: mov bp,sp ! 450: push di ! 451: push si ! 452: push ds ! 453: pop es ! 454: cld ! 455: mov bx,t ; BX = t ! 456: mov di,bx ; DI = t ! 457: xor al,al ; Search for 0 byte ! 458: mov cx,0FFFFh ! 459: repne scasb ! 460: dec di ; Back up to 0 ! 461: sub di,bx ; DI = length of t ! 462: jz spn1 ; Done if length of t is 0 ! 463: mov dx,di ; DX = length of t ! 464: mov si,s ; SI = s ! 465: mov cx,n ; CX = length of s ! 466: jcxz spn1 ; Check for null string ! 467: push bp ! 468: spn0: lodsb ; AL = next char in s ! 469: mov bp,cx ; BP = length of s ! 470: mov cx,dx ; CX = length of t ! 471: mov di,bx ; DI = t ! 472: repne scasb ; Scan until match found ! 473: mov cx,bp ; CX = length of s ! 474: loope spn0 ; Loop if match found ! 475: pop bp ! 476: je spn1 ; Skip ahead if end of s reached ! 477: dec si ; Back up one char ! 478: spn1: sub si,s ; SI = length of prefix ! 479: mov ax,si ; AX = length of prefix ! 480: pop si ! 481: pop di ! 482: pop bp ! 483: ret ! 484: _strnspn endp ! 485: ! 486: ! 487: ; int strncspn(s,t,n) ! 488: ; char *s; /* String to search */ ! 489: ; char *t; /* Target list */ ! 490: ; int n; /* Length of s */ ! 491: ! 492: EVEN ! 493: ! 494: public _strncspn ! 495: _strncspn proc near ! 496: push bp ! 497: mov bp,sp ! 498: push di ! 499: push si ! 500: push ds ! 501: pop es ! 502: cld ! 503: mov bx,t ; BX = t ! 504: mov di,bx ; DI = t ! 505: xor al,al ; Search for 0 byte ! 506: mov cx,0FFFFh ! 507: repne scasb ! 508: dec di ; Back up to 0 ! 509: sub di,bx ; DI = length of t ! 510: mov ax,n ; Assume length of t is 0 ! 511: jz cspn2 ; Done if length of t is 0 ! 512: mov dx,di ; DX = length of t ! 513: mov si,s ; SI = s ! 514: mov cx,ax ; CX = length of s ! 515: jcxz cspn1 ; Check for null string ! 516: push bp ! 517: cspn0: lodsb ; AL = next char in s ! 518: mov bp,cx ; BP = length of s ! 519: mov cx,dx ; CX = length of t ! 520: mov di,bx ; DI = t ! 521: repne scasb ; Scan until match found ! 522: mov cx,bp ; CX = length of s ! 523: loopne cspn0 ; Loop if match not found ! 524: pop bp ! 525: jne cspn1 ; Skip ahead if end of s reached ! 526: dec si ; Back up one char ! 527: cspn1: sub si,s ; SI = length of prefix ! 528: mov ax,si ; AX = length of prefix ! 529: cspn2: pop si ! 530: pop di ! 531: pop bp ! 532: ret ! 533: _strncspn endp ! 534: ! 535: ! 536: ; cmpsen - case-sensitive comparison ! 537: ; ! 538: ; ENTRY DS:SI = buffer ! 539: ; ES:DI = string ! 540: ; CX = length of string ! 541: ; EXIT CX = length of string unused ! 542: ; DI = unused portion of string ! 543: ; Z set ! 544: ; match found ! 545: ; Z clear ! 546: ; no match ! 547: ; USES CX, DI, SI, Flags ! 548: ! 549: EVEN ! 550: ! 551: cmpsen proc near ! 552: repe cmpsb ! 553: ret ! 554: cmpsen endp ! 555: ! 556: ! 557: ; cmpinsen - case-insensitive comparison ! 558: ; ! 559: ; ENTRY DS:SI = buffer ! 560: ; ES:DI = string ! 561: ; CX = length of string ! 562: ; EXIT CX = length of string unused ! 563: ; DI = unused portion of string ! 564: ; Z set ! 565: ; match found ! 566: ; Z clear ! 567: ; no match ! 568: ; USES AX, CX, DI, SI, Flags ! 569: ! 570: EVEN ! 571: ! 572: cmpinsen proc near ! 573: cmpi0: lodsb ; Byte in AL, SI = SI + 1 ! 574: mov ah,[di] ; Byte in AH, DI = DI + 1 ! 575: inc di ! 576: or ax,2020h ; Fold bytes onto lower case ! 577: cmp al,ah ; Compare bytes ! 578: loope cmpi0 ; Loop while same ! 579: ret ! 580: cmpinsen endp ! 581: ! 582: ! 583: ; void matchstrings(s1,s2,len,nmatched,leg) ! 584: ; char *s1; /* First string */ ! 585: ; char *s2; /* Second string */ ! 586: ; int len; /* Length */ ! 587: ; int *nmatched; /* Number of bytes matched */ ! 588: ; int *leg; /* Less than, equal, greater than */ ! 589: ! 590: cm_s1 equ word ptr [bp+retlen+2] ! 591: cm_s2 equ word ptr [bp+retlen+4] ! 592: cm_len equ word ptr [bp+retlen+6] ! 593: cm_nmatched equ word ptr [bp+retlen+8] ! 594: cm_leg equ word ptr [bp+retlen+10] ! 595: ! 596: EVEN ! 597: ! 598: public _matchstrings ! 599: _matchstrings proc near ! 600: ASSUME DS:DGROUP, ES:NOTHING, SS:DGROUP ! 601: ! 602: push bp ! 603: mov bp,sp ! 604: push di ! 605: push si ! 606: push ds ! 607: pop es ! 608: ASSUME ES:DGROUP ! 609: mov di,cm_s2 ! 610: mov si,cm_s1 ! 611: mov cx,cm_len ! 612: cmp _casesen,0 ! 613: je cm0 ! 614: call cmpsen ! 615: jmp short cm1 ! 616: cm0: call cmpinsen ! 617: cm1: mov bx,cm_leg ! 618: mov word ptr [bx],0 ; Assume equal ! 619: jz cm2 ; yes, skip ahead ! 620: mov word ptr [bx],1 ; Assume greater than ! 621: jg cm1a ; yes, skip ahead ! 622: mov word ptr [bx],-1 ; Less than ! 623: cm1a: dec si ! 624: cm2: sub si,cm_s1 ! 625: mov bx,cm_nmatched ! 626: mov [bx],si ! 627: pop si ! 628: pop di ! 629: pop bp ! 630: ret ! 631: ! 632: _matchstrings endp ! 633: ! 634: ! 635: ; int strcmp(s1,s2) ! 636: ; char *s1; /* First string */ ! 637: ; char *s2; /* Second string */ ! 638: ! 639: public _strcmp ! 640: _strcmp proc near ! 641: push bp ! 642: mov bp,sp ! 643: push di ! 644: push si ! 645: push ds ! 646: pop es ! 647: mov si,[bp+4] ; DS:SI = s1 ! 648: mov di,[bp+6] ; ES:DI = s2 ! 649: sc0: lodsb ; AL = *s1++ ! 650: scasb ; AL - *s2++ ! 651: jne sc1 ; branch if no match ! 652: or al,al ; End of s1? ! 653: jne sc0 ; no, loop ! 654: cbw ; AX = 0 ! 655: jmp short sc2 ; Exit ! 656: sc1: mov ax,1 ; Assume s1 > s2 ! 657: jg sc2 ; yes, branch ! 658: neg ax ; s1 < s2 ! 659: sc2: pop si ! 660: pop di ! 661: pop bp ! 662: ret ! 663: _strcmp endp ! 664: ! 665: ! 666: public _bpt ! 667: _bpt proc near ! 668: int 3 ! 669: ret ! 670: _bpt endp ! 671: ! 672: _text ends ! 673: ! 674: _data segment word public 'data' ! 675: _data ends ! 676: ! 677: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.