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