~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
; Copyright (C) 2000, 2003 MySQL AB
2
; 
3
; This library is free software; you can redistribute it and/or
4
; modify it under the terms of the GNU Library General Public
5
; License as published by the Free Software Foundation; version 2
6
; of the License.
7
; 
8
; This library is distributed in the hope that it will be useful,
9
; but WITHOUT ANY WARRANTY; without even the implied warranty of
10
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
; Library General Public License for more details.
12
; 
13
; You should have received a copy of the GNU Library General Public
14
; License along with this library; if not, write to the Free
15
; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16
; MA 02111-1307, USA
17
18
; Note that if you don't have a macro assembler (like MASM) to compile
19
; this file, you can instead compile all *.c files in the string
20
; directory.
21
22
	TITLE   Stringfunctions that we use often at MSDOS / Intel 8086
23
24
ifndef M_I386
25
	.8087
26
	DOSSEG
27
	.MODEL LARGE
28
	.CODE
29
30
	;
31
	; Some macros
32
	;
33
34
q_movs	MACRO				; as rep movsb but quicker
35
	shr	cx,1
36
	rep	movsw			; Move 2 bytes at a time
37
	adc	cx,cx
38
	rep	movsb			; Move last byte if any
39
	ENDM
40
41
q_stos	MACRO				; as rep stosb but quicker
42
	mov	ah,al			; For word store
43
	shr	cx,1
44
	rep	stosw			; Move 2 bytes at a time
45
	adc	cx,cx
46
	rep	stosb			; Move last byte if any
47
 	ENDM
48
49
ifndef  ZTC				; If not using ZORTECH compiler
50
	;
51
	; Compare memory
52
	; Args: s1,s2,length
53
	;
54
55
	PUBLIC	_bcmp
56
_bcmp	PROC
57
	mov	bx,bp			; Save bp
58
	mov	dx,di			; Save di
59
	mov	bp,sp
60
	push	ds
61
	push	si
62
	les	di,DWORD PTR [bp+8]	; s2
63
	lds	si,DWORD PTR [bp+4]	; s1
64
	mov	cx,WORD PTR [bp+12]	; Length of memory-area
65
	jcxz	@F			; Length = 0, return same
66
;	cld				; Work uppward
67
	repe	cmpsb			; Compare strings
68
	jz	@F			; Match found
69
	inc	cx			; return matchpoint +1
70
@@:	mov	ax,cx			; Return 0 if match, else pos from end
71
	pop	si
72
	pop	ds
73
	mov	di,dx
74
	mov	bp,bx
75
	ret
76
_bcmp	ENDP
77
78
	;
79
	; Find a char in a string
80
	; Arg: str,char
81
	; Ret: pointer to found char or NullS
82
	;
83
84
ifdef better_stringfunctions		; Breaks window linkage (broken linking)
85
86
	PUBLIC	_strchr
87
_strchr	PROC
88
	mov	bx,bp			; Save bp and di
89
	mov	dx,di
90
	mov	bp,sp
91
	les	di,DWORD PTR [bp+4]	; str
92
	mov	ah,BYTE PTR [bp+8]	; search
93
	xor	al,al			; for scasb to find end
94
95
@@:	cmp	ah,es:[di]
96
	jz	@F			; Found char
97
	scasb
98
	jnz	@B			; Not end
99
	xor	di,di			; Not found
100
	mov	es,di
101
@@:	mov	ax,di
102
	mov	di,dx			; Restore
103
	mov	dx,es			; Seg adr
104
	mov	bp,bx			; Restore
105
	ret
106
_strchr	ENDP
107
108
	;
109
	; Find length of string
110
	; arg: str
111
	; ret: length
112
	;
113
114
	PUBLIC	_strlen
115
_strlen	PROC
116
	mov	bx,sp
117
	mov	dx,di
118
	les	di,DWORD PTR ss:[bx+4]	; Str
119
	xor	al,al			; Find end of string
120
	mov	cx,-1
121
;	cld
122
	repne	scasb			; Find strend or length
123
	inc	cx			; Calc strlength
124
	not	cx
125
	mov	ax,cx
126
	mov	di,dx			; Restore register
127
	ret
128
_strlen	ENDP
129
130
endif
131
132
	;
133
	; Move a string
134
	; arg: dst,src
135
	; ret: end-null of to
136
	;
137
138
	PUBLIC	_strmov
139
_strmov	PROC
140
	mov	bx,bp
141
	mov	cx,si
142
	mov	bp,sp
143
	push	ds
144
	push	di
145
	les	di,DWORD PTR [bp+4]	; dst
146
	lds	si,DWORD PTR [bp+8]	; src
147
;	cld
148
@@:	mov	al,ds:[si]
149
	movsb				; move arg
150
	and	al,al
151
	jnz	@B			; Not last
152
	lea	ax,WORD PTR [di-1]	; Set DX:AX to point at last null
153
	mov	dx,es
154
	pop	di
155
	pop	ds
156
	mov	si,cx
157
	mov	bp,bx
158
	ret
159
_strmov	ENDP
160
161
	;
162
	; Fill a area of memory with a walue
163
	; Args: to,length,fillchar
164
	;
165
166
	PUBLIC	_bfill
167
_bfill	PROC
168
	mov	bx,sp			; Get args through BX
169
	mov	al,BYTE PTR ss:[bx+10]	; Fill
170
bfill_10:
171
	mov	dx,di			; Save di
172
	les	di,DWORD PTR ss:[bx+4]	; Memory pointer
173
	mov	cx,WORD PTR ss:[bx+8]	; Length
174
;	cld
175
	q_stos
176
	mov	di,dx
177
	ret
178
_bfill	ENDP
179
180
	;
181
	; Fill a area with null
182
	; Args: to,length
183
184
	PUBLIC	_bzero
185
_bzero	PROC
186
	mov	bx,sp			; Get args through BX
187
	mov	al,0			; Fill with null
188
	jmp	short bfill_10
189
_bzero	ENDP
190
191
endif	; ZTC
192
193
	;
194
	; Move a memory area
195
	; Args: to,from,length
196
	;
197
198
	PUBLIC	_bmove
199
_bmove	PROC
200
	mov	bx,bp
201
	mov	dx,di
202
	mov	ax,si
203
	mov	bp,sp
204
	push	ds
205
	lds	si,DWORD PTR [bp+8]	; from
206
	les	di,DWORD PTR [bp+4]	; to
207
	mov	cx,WORD PTR [bp+12]	; Length of memory-area
208
;	cld				; Work uppward
209
	rep	movsb			; Not q_movs because overlap ?
210
	pop	ds
211
	mov	si,ax
212
	mov	di,dx
213
	mov	bp,bx
214
	ret
215
_bmove	ENDP
216
217
	;
218
	; Move a alligned, not overlapped, by (long) divided memory area
219
	; Args: to,from,length
220
	;
221
222
	PUBLIC	_bmove_align
223
_bmove_align	PROC
224
	mov	bx,bp
225
	mov	dx,di
226
	mov	ax,si
227
	mov	bp,sp
228
	push	ds
229
	lds	si,DWORD PTR [bp+8]	; from
230
	les	di,DWORD PTR [bp+4]	; to
231
	mov	cx,WORD PTR [bp+12]	; Length of memory-area
232
;	cld				; Work uppward
233
	inc	cx			; fix if not divisible with word
234
	shr	cx,1
235
	rep	movsw			; Move 2 bytes at a time
236
	pop	ds
237
	mov	si,ax
238
	mov	di,dx
239
	mov	bp,bx
240
	ret
241
_bmove_align	ENDP
242
243
	;
244
	; Move a string from higher to lower
245
	; Arg from+1,to+1,length
246
	;
247
248
	PUBLIC	_bmove_upp
249
_bmove_upp	PROC
250
	mov	bx,bp
251
	mov	dx,di
252
	mov	ax,si
253
	mov	bp,sp
254
	push	ds
255
	lds	si,DWORD PTR [bp+8]	; from
256
	les	di,DWORD PTR [bp+4]	; to
257
	mov	cx,WORD PTR [bp+12]	; Length of memory-area
258
	dec	di			; Don't move last arg
259
	dec	si
260
	std				; Work downward
261
	rep	movsb			; Not q_movs because overlap ?
262
	cld				; C compilator want cld
263
	pop	ds
264
	mov	si,ax
265
	mov	di,dx
266
	mov	bp,bx
267
	ret
268
_bmove_upp ENDP
269
270
	;
271
	; Append fillchars to string
272
	; Args: dest,len,fill
273
	;
274
275
	PUBLIC	_strappend
276
_strappend	PROC
277
	mov	bx,bp
278
	mov	dx,di
279
	mov	bp,sp
280
	les	di,DWORD PTR [bp+4]	; Memory pointer
281
	mov	cx,WORD PTR [bp+8]	; Length
282
	sub	al,al			; Find end of string
283
;	cld
284
	repne	scasb
285
	jnz	sa_99			; String to long, shorten it
286
	mov	al,BYTE PTR [bp+10]	; Fillchar
287
	dec	di			; Point at end null
288
	inc	cx			; rep made one dec for null-char
289
	q_stos				; Store al in string
290
sa_99:	mov	BYTE PTR es:[di],0	; End of string
291
	mov	di,dx
292
	mov	bp,bx
293
	ret
294
_strappend	ENDP
295
296
	;
297
	; Find if string contains any char in another string
298
	; Arg: str,set
299
	; Ret: Pointer to first found char in str
300
	;
301
302
	PUBLIC	_strcont
303
_strcont	PROC
304
	mov	bx,bp			; Save bp and di in regs
305
	mov	dx,di
306
	mov	bp,sp
307
	push	ds
308
	push	si
309
	lds	si,DWORD PTR [bp+4]	; str
310
	les	di,DWORD PTR [bp+8]	; Set
311
	mov	cx,di			; Save for loop
312
	xor	ah,ah			; For endtest
313
	jmp	sc_60
314
315
sc_10:	scasb
316
	jz	sc_fo			; Found char
317
sc_20:	cmp	ah,es:[di]		; Test if null
318
	jnz	sc_10			; Not end of set yet
319
	inc	si			; Next char in str
320
	mov	di,cx			; es:di = Set
321
sc_60:	mov	al,ds:[si]		; Test if this char exist
322
	and	al,al
323
	jnz	sc_20			; Not end of string
324
	sub	si,si			; Return Null
325
	mov	ds,si
326
sc_fo:	mov	ax,si			; Char found here
327
	mov	di,dx			; Restore
328
	mov	dx,ds			; Seg of found char
329
	pop	si
330
	pop	ds
331
	mov	bp,bx
332
	ret
333
_strcont	ENDP
334
335
	;
336
	; Found end of string
337
	; Arg: str
338
	; ret: Pointer to end null
339
	;
340
341
	PUBLIC	_strend
342
_strend	PROC
343
	mov	bx,sp
344
	mov	dx,di			; Save
345
	les	di,DWORD PTR ss:[bx+4]	; str
346
	mov	cx,-1
347
	sub	al,al			; Find end of string
348
;	cld
349
	repne	scasb
350
	lea	ax,WORD PTR [di-1]	; Endpos i DX:AX
351
	mov	di,dx			; Restore
352
	mov	dx,es
353
	ret
354
_strend	ENDP
355
356
	;
357
	; Make a string with len fill-chars and endnull
358
	; Args: dest,len,fill
359
	; Ret:  dest+len
360
	;
361
362
	PUBLIC	_strfill
363
_strfill	PROC
364
	mov	bx,bp			; Save sp
365
	mov	bp,sp
366
	push	di
367
	les	di,DWORD PTR [bp+4]	; Memory pointer
368
	mov	cx,WORD PTR [bp+8]	; Length
369
	mov	al,BYTE PTR [bp+10]	; Fill
370
;	cld
371
	q_stos
372
	mov	BYTE PTR es:[di],0	; End NULL
373
	mov	ax,di			; End i DX:AX
374
	mov	dx,es
375
	pop	di
376
	mov	bp,bx
377
	ret
378
_strfill	ENDP
379
380
	;
381
	; Find a char in or end of a string
382
	; Arg: str,char
383
	; Ret: pointer to found char or NullS
384
	;
385
386
	PUBLIC	_strcend
387
_strcend	PROC
388
	mov	bx,bp			; Save bp and di
389
	mov	dx,di
390
	mov	bp,sp
391
	les	di,DWORD PTR [bp+4]	; str
392
	mov	ah,BYTE PTR [bp+8]	; search
393
	xor	al,al			; for scasb to find end
394
395
@@:	cmp	ah,es:[di]
396
	jz	@F			; Found char
397
	scasb
398
	jnz	@B			; Not end
399
	dec 	di			; Not found, point at end of string
400
@@:	mov	ax,di
401
	mov	di,dx			; Restore
402
	mov	dx,es			; Seg adr
403
	mov	bp,bx			; Restore
404
	ret
405
_strcend	ENDP
406
407
	;
408
	; Test if string has a given suffix
409
	;
410
411
PUBLIC  _is_prefix
412
_is_prefix PROC
413
	mov	dx,di			; Save di
414
	mov	bx,sp			; Arguments through bx
415
	push	ds
416
	push	si
417
	les	di,DWORD PTR ss:[bx+8]	; s2
418
	lds	si,DWORD PTR ss:[bx+4]	; s1
419
	mov	ax,1			; Ok and zero-test
420
;	cld				; Work uppward
421
@@:	cmp	ah,es:[di]
422
	jz	suf_ok			; End of string; found suffix
423
	cmpsb				; Compare strings
424
	jz	@B			; Same, possible prefix
425
	xor	ax,ax			; Not suffix
426
suf_ok:	pop	si
427
	pop	ds
428
	mov	di,dx
429
	ret
430
_is_prefix ENDP
431
432
	;
433
	; Find a substring in string
434
	; Arg: str,search
435
	;
436
437
	PUBLIC	_strstr
438
_strstr	PROC
439
	mov	bx,bp
440
	mov	bp,sp
441
	push	ds
442
	push	di
443
	push	si
444
	lds	si,DWORD PTR [bp+4]	; str
445
	les	di,DWORD PTR [bp+8]	; search
446
	mov	cx,di
447
	inc	cx			; CX = search+1
448
	mov	ah,es:[di]		; AH = First char in search
449
	jmp	sf_10
450
451
sf_00:	mov	si,dx			; si = Current str-pos
452
sf_10:	mov	al,ds:[si]		; Test if this char exist
453
	and	al,al
454
	jz	sf_90			; End of string, didn't find search
455
	inc	si
456
	cmp	al,ah
457
	jnz	sf_10			; Didn't find first char, continue
458
	mov	dx,si			; Save str-pos in DX
459
	mov	di,cx
460
sf_20:	cmp	BYTE PTR es:[di],0
461
	jz	sf_fo			; Found substring
462
	cmpsb
463
	jz	sf_20			; Char ok
464
	jmp	sf_00			; Next str-pos
465
466
sf_90:	sub	dx,dx			; Return Null
467
	mov	ds,dx
468
	inc	dx			; Because of following dec
469
sf_fo:	mov	ax,dx			; Char found here
470
	dec	ax			; Pointed one after
471
	mov	dx,ds
472
	pop	si
473
	pop	di			; End
474
	pop	ds
475
	mov	bp,bx
476
	ret
477
_strstr	ENDP
478
479
	;
480
	; Make a string of len length from another string
481
	; Arg: dst,src,length
482
	; ret: end of dst
483
	;
484
485
	PUBLIC	_strmake
486
_strmake	PROC
487
	mov	bx,bp
488
	mov	bp,sp
489
	push	ds
490
	push	di
491
	push	si
492
	les	di,DWORD PTR [bp+4]	; dst
493
	lds	si,DWORD PTR [bp+8]	; src
494
	mov	cx,WORD PTR [bp+12]	; Length of memory-area
495
	xor	al,al			; For test of end-null
496
	jcxz	sm_90			; Nothing to move, put zero at end.
497
;	cld				; Work uppward
498
499
@@:	cmp	al,ds:[si]		; Next char to move
500
	movsb				; move arg
501
	jz	sm_99			; last char, we are ready
502
	loop	@B			; Continue moving
503
sm_90:	mov	BYTE PTR es:[di],al	; Set end pos
504
	inc	di			; Fix that di points at end null
505
sm_99:	dec	di			; di points now at end null
506
	mov	ax,di			; Ret value in DX:AX
507
	mov	dx,es
508
	pop	si
509
	pop	di
510
	pop	ds
511
	mov	bp,bx
512
	ret
513
_strmake	ENDP
514
515
	;
516
	; Find length of string with maxlength
517
	; arg: str,maxlength
518
	; ret: length
519
	;
520
521
	PUBLIC	_strnlen
522
_strnlen	PROC
523
	mov	bx,bp
524
	mov	bp,sp
525
	push	di
526
	les	di,DWORD PTR [bp+4]	; Str
527
	mov	cx,WORD PTR [bp+8]	; length
528
	mov	dx,di			; Save str to calc length
529
	jcxz	sn_10			; Length = 0
530
	xor	al,al			; Find end of string
531
;	cld
532
	repne	scasb			; Find strend or length
533
	jnz	sn_10
534
	dec	di			; DI points at last null
535
sn_10:	mov	ax,di
536
	sub	ax,dx			; Ax = length
537
	pop	di
538
	mov	bp,bx
539
	ret
540
_strnlen	ENDP
541
542
	;
543
	; Move a string with max len chars
544
	; arg: dst,src,len
545
	; ret: pos to first null or dst+len
546
547
	PUBLIC	_strnmov
548
_strnmov	PROC
549
	mov	bx,bp
550
	mov	bp,sp
551
	push	ds
552
	push	di
553
	push	si
554
	les	di,DWORD PTR [bp+4]	; dst
555
	lds	si,DWORD PTR [bp+8]	; src
556
	mov	cx,WORD PTR [bp+12]	; length
557
	jcxz	snm_99			; Nothing to do
558
	xor	al,al			; For test of end-null
559
;	cld
560
561
@@:	cmp	al,ds:[si]		; Next char to move
562
	movsb				; move arg
563
	jz	snm_20			; last char, fill with null
564
	loop	@B			; Continue moving
565
	inc	di			; Point two after last
566
snm_20:	dec	di			; Point at first null (or last+1)
567
snm_99:	mov	ax,di			; Pointer at last char
568
	mov	dx,es			; To-segment
569
	pop	si
570
	pop	di
571
	pop	ds
572
	mov	bp,bx			; Restore
573
	ret
574
_strnmov	ENDP
575
576
else	; M_I386
577
578
include macros.asm
579
580
q_stos	MACRO				; as rep stosb but quicker, Uses edx
581
	mov	ah,al			;(2) Set up a 32 bit pattern.
582
	mov	edx,eax			;(2)
583
	shl	edx,16			;(3)
584
	or	eax,edx			;(2) EAX has the 32 bit pattern.
585
586
	mov	edx,ecx			;(2) Save the count of bytes.
587
	shr	ecx,2			;(2) Number of dwords.
588
	rep	stosd			;(5 + 5n)
589
	mov	cl,3			;(2)
590
	and	ecx,edx			;(2) Fill in the remaining odd bytes.
591
	rep	stosb			; Move last bytes if any
592
	ENDM
593
594
fix_es	MACRO	fix_cld			; Load ES if neaded
595
  ife ESeqDS
596
	mov	ax,ds
597
	mov	es,ax
598
  endif
599
  ifnb <fix_cld>
600
	cld
601
  endif
602
	ENDM
603
604
	;
605
	; Move a memory area
606
	; Args: to,from,length
607
	; Acts as one byte was moved a-time from dst to source.
608
	;
609
610
	begcode bmove
611
	public	_bmove
612
_bmove	proc near
613
	fix_es	1
614
	mov	edx,edi
615
	mov	eax,esi
616
	mov	edi,P-SIZEPTR[esp]	;p1
617
	mov	esi,P[esp]		;p2
618
	mov	ecx,P+SIZEPTR[esp]
619
	rep	movsb			; Not q_movs because overlap ?
620
	mov	esi,eax
621
	mov	edi,edx
622
	ret
623
_bmove	ENDP
624
	endcode bmove
625
626
	;
627
	; Move a alligned, not overlapped, by (long) divided memory area
628
	; Args: to,from,length
629
	;
630
631
	begcode	bmove_align
632
	public	_bmove_align
633
_bmove_align	proc near
634
	fix_es	1
635
	mov	edx,edi
636
	mov	eax,esi
637
	mov	edi,P-SIZEPTR[esp]	;to
638
	mov	esi,P[esp]		;from
639
	mov	ecx,P+SIZEPTR[esp]	;length
640
	add	cx,3			;fix if not divisible with long
641
	shr	cx,2
642
	rep	movsd
643
	mov	esi,eax
644
	mov	edi,edx
645
	ret
646
_bmove_align	ENDP
647
	endcode bmove_align
648
649
	;
650
	; Move a string from higher to lower
651
	; Arg from+1,to+1,length
652
	;
653
654
	begcode	bmove_upp
655
	public	_bmove_upp
656
_bmove_upp	proc near
657
	fix_es
658
	std				; Work downward
659
	mov	edx,edi
660
	mov	eax,esi
661
	mov	edi,P-SIZEPTR[esp]	;p1
662
	mov	esi,P[esp]		;p2
663
	mov	ecx,P+SIZEPTR[esp]
664
	dec	edi			; Don't move last arg
665
	dec	esi
666
	rep	movsb			; One byte a time because overlap !
667
	cld				; C compilator wants cld
668
	mov	esi,eax
669
	mov	edi,edx
670
	ret
671
_bmove_upp ENDP
672
	endcode bmove_upp
673
674
	;
675
	; Append fillchars to string
676
	; Args: dest,len,fill
677
	;
678
679
	begcode	strappend
680
	public	_strappend
681
_strappend	proc near
682
	push	ebp
683
	mov	ebp,esp
684
	fix_es  1
685
	push	edi
686
	mov	edi,P[ebp]		; Memory pointer
687
	mov	ecx,P+SIZEPTR[ebp]	; Length
688
	clr	eax			; Find end of string
689
	repne	scasb
690
	jnz	sa_99			; String to long, shorten it
691
	movzx	eax,byte ptr P+(2*SIZEPTR)[ebp]	; Fillchar
692
	dec	edi			; Point at end null
693
	inc	ecx			; rep made one dec for null-char
694
	q_stos				; Store al in string
695
sa_99:	mov	BYTE PTR [edi],0	; End of string
696
	pop	edi
697
	pop	ebp
698
	ret
699
_strappend	ENDP
700
	endcode strappend
701
702
	;
703
	; Find if string contains any char in another string
704
	; Arg: str,set
705
	; Ret: Pointer to first found char in str
706
	;
707
708
	begcode strcont
709
	PUBLIC	_strcont
710
_strcont proc near
711
	push	ebp
712
	mov	ebp,esp
713
	fix_es	1
714
	mov	edx,edi
715
	push	esi
716
	mov	esi,P[ebp]		; str
717
	mov	ecx,P+SIZEPTR[ebp]	; Set
718
	clr	ah			; For endtest
719
	jmps	sc_60
720
721
sc_10:	scasb
722
	jz	sc_fo			; Found char
723
sc_20:	cmp	ah,[edi]		; Test if null
724
	jnz	sc_10			; Not end of set yet
725
	inc	esi			; Next char in str
726
sc_60:	mov	edi,ecx			; edi = Set
727
	mov	al,[esi]		; Test if this char exist
728
	and	al,al
729
	jnz	sc_20			; Not end of string
730
	clr	esi			; Return Null
731
sc_fo:	mov	eax,esi			; Char found here
732
	mov	edi,edx			; Restore
733
	pop	esi
734
	pop	ebp
735
	ret
736
_strcont	ENDP
737
	endcode strcont
738
739
	;
740
	; Found end of string
741
	; Arg: str
742
	; ret: Pointer to end null
743
	;
744
745
	begcode strend
746
	public	_strend
747
_strend	proc near
748
	fix_es	1
749
	mov	edx,edi			; Save
750
	mov	edi,P-SIZEPTR[esp]	; str
751
	clr	eax			; Find end of string
752
	mov	ecx,eax
753
	dec	ecx			; ECX = -1
754
	repne	scasb
755
	mov	eax,edi
756
	dec	eax
757
	mov	edi,edx			; Restore
758
	ret
759
_strend	endp
760
	endcode strend
761
762
	;
763
	; Make a string with len fill-chars and endnull
764
	; Args: dest,len,fill
765
	; Ret:  dest+len
766
	;
767
768
	begcode	strfill
769
	public	_strfill
770
_strfill proc near
771
	push	ebp
772
	mov	ebp,esp
773
	fix_es  1
774
	push	edi
775
	mov	edi,P[ebp]		; Memory pointer
776
	mov	ecx,P+SIZEPTR[ebp]	; Length
777
	movzx	eax,byte ptr P+(2*SIZEPTR)[ebp]	; Fill
778
	q_stos
779
	mov	BYTE PTR [edi],0	; End NULL
780
	mov	eax,edi			; End i DX:AX
781
	pop	edi
782
	pop	ebp
783
	ret
784
_strfill endp
785
	endcode strfill
786
787
	;
788
	; Find a char in or end of a string
789
	; Arg: str,char
790
	; Ret: pointer to found char or NullS
791
	;
792
793
	begcode strcend
794
	public	_strcend
795
_strcend proc near
796
	push	ebp
797
	mov	ebp,esp
798
	fix_es  1
799
	mov	edx,edi
800
	mov	edi,P[ebp]		; str
801
	mov	ah,P+SIZEPTR[ebp]	; search
802
	clr	al			; for scasb to find end
803
804
@@:	cmp	ah,[edi]
805
	jz	@F			; Found char
806
	scasb
807
	jnz	@B			; Not end
808
	dec 	edi			; Not found, point at end of string
809
@@:	mov	eax,edi
810
	mov	edi,edx			; Restore
811
	pop	ebp
812
	ret
813
_strcend	ENDP
814
	endcode strcend
815
816
	;
817
	; Test if string has a given suffix
818
	;
819
820
	begcode is_prefix
821
	public	_is_prefix
822
_is_prefix proc near
823
	fix_es	1
824
	mov	edx,edi			; Save edi
825
	mov	eax,esi			; Save esi
826
	mov	esi,P[esp]		; get suffix
827
	mov	edi,P-SIZEPTR[esp]	; s1
828
	push	eax			; push esi
829
	mov	eax,1			; Ok and zero-test
830
@@:	cmp	ah,[esi]
831
	jz	suf_ok			; End of string; found suffix
832
	cmpsb				; Compare strings
833
	jz	@B			; Same, possible prefix
834
	xor	eax,eax			; Not suffix
835
suf_ok:	pop	esi
836
	mov	edi,edx
837
	ret
838
_is_prefix endp
839
	endcode	_is_prefix
840
841
	;
842
	; Find a substring in string
843
	; Arg: str,search
844
	;
845
846
	begcode strstr
847
	public	_strstr
848
_strstr proc near
849
	push	ebp
850
	mov	ebp,esp
851
	fix_es	1
852
	push	EDI
853
	push	ESI
854
	mov	esi,P[ebp]		; str
855
	mov	edi,P+SIZEPTR[ebp]	; search
856
	mov	ecx,edi
857
	inc	ecx			; ECX = search+1
858
	mov	ah,[edi]		; AH = First char in search
859
	jmps	sf_10
860
861
sf_00:	mov	esi,edx			; si = Current str-pos
862
sf_10:	mov	al,[esi]		; Test if this char exist
863
	and	al,al
864
	jz	sf_90			; End of string, didn't find search
865
	inc	esi
866
	cmp	al,ah
867
	jnz	sf_10			; Didn't find first char, continue
868
	mov	edx,esi			; Save str-pos in EDX
869
	mov	edi,ecx
870
sf_20:	cmp	BYTE PTR [edi],0
871
	jz	sf_fo			; Found substring
872
	cmpsb
873
	jz	sf_20			; Char ok
874
	jmps	sf_00			; Next str-pos
875
876
sf_90:	mov	edx,1			; Return Null
877
sf_fo:	mov	eax,edx			; Char found here
878
	dec	eax			; Pointed one after
879
	pop	ESI
880
	pop	EDI
881
	pop	ebp
882
	ret
883
_strstr endp
884
	endcode strstr
885
886
	;
887
	; Make a string of len length from another string
888
	; Arg: dst,src,length
889
	; ret: end of dst
890
	;
891
892
	begcode strmake
893
	public	_strmake
894
_strmake proc near
895
	push	ebp
896
	mov	ebp,esp
897
	fix_es	1
898
	push	EDI
899
	push	ESI
900
	mov	edi,P[ebp]		; dst
901
	mov	esi,P+SIZEPTR[ebp]	; src
902
	mov	ecx,P+SIZEPTR*2[ebp]	; Length of memory-area
903
	clr	al			; For test of end-null
904
	jcxz	sm_90			; Nothing to move, put zero at end.
905
906
@@:	cmp	al,[esi]		; Next char to move
907
	movsb				; move arg
908
	jz	sm_99			; last char, we are ready
909
	loop	@B			; Continue moving
910
sm_90:	mov	BYTE PTR [edi],al	; Set end pos
911
	inc	edi			; Fix that di points at end null
912
sm_99:	dec	edi			; di points now at end null
913
	mov	eax,edi			; Ret value in DX:AX
914
	pop	ESI
915
	pop	EDI
916
	pop	ebp
917
	ret
918
_strmake	ENDP
919
	endcode strmake
920
921
	;
922
	; Find length of string with maxlength
923
	; arg: str,maxlength
924
	; ret: length
925
	;
926
927
	begcode	strnlen
928
	public	_strnlen
929
_strnlen proc near
930
	push	ebp
931
	mov	ebp,esp
932
	fix_es	1
933
	push	edi
934
	mov	edi,P[ebp]		; Str
935
	mov	ecx,P+SIZEPTR[ebp]	; length
936
	mov	edx,edi			; Save str to calc length
937
	jcxz	sn_10			; Length = 0
938
	clr	al			; Find end of string
939
	repne	scasb			; Find strend or length
940
	jnz	sn_10
941
	dec	edi			; DI points at last null
942
sn_10:	mov	eax,edi
943
	sub	eax,edx			; Ax = length
944
	pop	edi
945
	pop	ebp
946
	ret
947
_strnlen	ENDP
948
	endcode strnlen
949
950
	;
951
	; Move a string with max len chars
952
	; arg: dst,src,len
953
	; ret: pos to first null or dst+len
954
955
	begcode	strnmov
956
	public	_strnmov
957
_strnmov PROC near
958
	push	ebp
959
	mov	ebp,esp
960
	fix_es	1
961
	push	EDI
962
	push	ESI
963
	mov	edi,P[ebp]		; dst
964
	mov	esi,P+SIZEPTR[ebp]	; src
965
	mov	ecx,P+(SIZEPTR*2)[ebp]	; length
966
	jcxz	snm_99			; Nothing to do
967
	clr	al			; For test of end-null
968
969
@@:	cmp	al,[esi]		; Next char to move
970
	movsb				; move arg
971
	jz	snm_20			; last char, fill with null
972
	loop	@B			; Continue moving
973
	inc	edi			; Point two after last
974
snm_20:	dec	edi			; Point at first null (or last+1)
975
snm_99:	mov	eax,edi			; Pointer at last char
976
	pop	ESI
977
	pop	EDI
978
	pop	ebp
979
	ret
980
_strnmov	ENDP
981
	endcode strnmov
982
983
;
984
; Zortech has this one in standard library
985
;
986
987
	begcode strmov
988
	public	_strmov
989
_strmov proc	near
990
	mov	ecx,esi			; Save old esi and edi
991
	mov	edx,edi
992
	mov	esi,P[esp]		; get source pointer (s2)
993
	mov	edi,P-SIZEPTR[esp]	; EDI -> s1
994
	fix_es	1
995
@@:	mov	al,[esi]
996
	movsb				; move arg
997
	and	al,al
998
	jnz	@B			; Not last
999
	mov	eax,edi
1000
	dec	eax
1001
	mov	esi,ecx			; Restore args
1002
	mov	edi,edx
1003
	ret
1004
_strmov endp
1005
	endcode strmov
1006
1007
endif ; M_I386
1008
1009
	END