|
|
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.