~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
	; Find a substring in string, return index
481
	; Arg: str,search
482
	;
483
484
	PUBLIC	_strinstr
485
_strinstr	PROC
486
	push	bp
487
	mov	bp,sp
488
	push	di
489
	les	di,DWORD PTR [bp+10]	; search
490
	push	es
491
	push	di
492
	les	di,DWORD PTR [bp+6]	; str
493
	push	es
494
	push	di
495
	call	_strstr
496
	mov	cx,ax
497
	or	cx,dx
498
	jz	si_99
499
	sub	ax,di			; Pos from start
500
	inc	ax			; And first pos = 1
501
si_99:	add	sp,8
502
	pop	di
503
	pop	bp
504
	ret
505
_strinstr	ENDP
506
507
	;
508
	; Make a string of len length from another string
509
	; Arg: dst,src,length
510
	; ret: end of dst
511
	;
512
513
	PUBLIC	_strmake
514
_strmake	PROC
515
	mov	bx,bp
516
	mov	bp,sp
517
	push	ds
518
	push	di
519
	push	si
520
	les	di,DWORD PTR [bp+4]	; dst
521
	lds	si,DWORD PTR [bp+8]	; src
522
	mov	cx,WORD PTR [bp+12]	; Length of memory-area
523
	xor	al,al			; For test of end-null
524
	jcxz	sm_90			; Nothing to move, put zero at end.
525
;	cld				; Work uppward
526
527
@@:	cmp	al,ds:[si]		; Next char to move
528
	movsb				; move arg
529
	jz	sm_99			; last char, we are ready
530
	loop	@B			; Continue moving
531
sm_90:	mov	BYTE PTR es:[di],al	; Set end pos
532
	inc	di			; Fix that di points at end null
533
sm_99:	dec	di			; di points now at end null
534
	mov	ax,di			; Ret value in DX:AX
535
	mov	dx,es
536
	pop	si
537
	pop	di
538
	pop	ds
539
	mov	bp,bx
540
	ret
541
_strmake	ENDP
542
543
	;
544
	; Find length of string with maxlength
545
	; arg: str,maxlength
546
	; ret: length
547
	;
548
549
	PUBLIC	_strnlen
550
_strnlen	PROC
551
	mov	bx,bp
552
	mov	bp,sp
553
	push	di
554
	les	di,DWORD PTR [bp+4]	; Str
555
	mov	cx,WORD PTR [bp+8]	; length
556
	mov	dx,di			; Save str to calc length
557
	jcxz	sn_10			; Length = 0
558
	xor	al,al			; Find end of string
559
;	cld
560
	repne	scasb			; Find strend or length
561
	jnz	sn_10
562
	dec	di			; DI points at last null
563
sn_10:	mov	ax,di
564
	sub	ax,dx			; Ax = length
565
	pop	di
566
	mov	bp,bx
567
	ret
568
_strnlen	ENDP
569
570
	;
571
	; Move a string with max len chars
572
	; arg: dst,src,len
573
	; ret: pos to first null or dst+len
574
575
	PUBLIC	_strnmov
576
_strnmov	PROC
577
	mov	bx,bp
578
	mov	bp,sp
579
	push	ds
580
	push	di
581
	push	si
582
	les	di,DWORD PTR [bp+4]	; dst
583
	lds	si,DWORD PTR [bp+8]	; src
584
	mov	cx,WORD PTR [bp+12]	; length
585
	jcxz	snm_99			; Nothing to do
586
	xor	al,al			; For test of end-null
587
;	cld
588
589
@@:	cmp	al,ds:[si]		; Next char to move
590
	movsb				; move arg
591
	jz	snm_20			; last char, fill with null
592
	loop	@B			; Continue moving
593
	inc	di			; Point two after last
594
snm_20:	dec	di			; Point at first null (or last+1)
595
snm_99:	mov	ax,di			; Pointer at last char
596
	mov	dx,es			; To-segment
597
	pop	si
598
	pop	di
599
	pop	ds
600
	mov	bp,bx			; Restore
601
	ret
602
_strnmov	ENDP
603
604
else	; M_I386
605
606
include macros.asm
607
608
q_stos	MACRO				; as rep stosb but quicker, Uses edx
609
	mov	ah,al			;(2) Set up a 32 bit pattern.
610
	mov	edx,eax			;(2)
611
	shl	edx,16			;(3)
612
	or	eax,edx			;(2) EAX has the 32 bit pattern.
613
614
	mov	edx,ecx			;(2) Save the count of bytes.
615
	shr	ecx,2			;(2) Number of dwords.
616
	rep	stosd			;(5 + 5n)
617
	mov	cl,3			;(2)
618
	and	ecx,edx			;(2) Fill in the remaining odd bytes.
619
	rep	stosb			; Move last bytes if any
620
	ENDM
621
622
fix_es	MACRO	fix_cld			; Load ES if neaded
623
  ife ESeqDS
624
	mov	ax,ds
625
	mov	es,ax
626
  endif
627
  ifnb <fix_cld>
628
	cld
629
  endif
630
	ENDM
631
632
	;
633
	; Move a memory area
634
	; Args: to,from,length
635
	; Acts as one byte was moved a-time from dst to source.
636
	;
637
638
	begcode bmove
639
	public	_bmove
640
_bmove	proc near
641
	fix_es	1
642
	mov	edx,edi
643
	mov	eax,esi
644
	mov	edi,P-SIZEPTR[esp]	;p1
645
	mov	esi,P[esp]		;p2
646
	mov	ecx,P+SIZEPTR[esp]
647
	rep	movsb			; Not q_movs because overlap ?
648
	mov	esi,eax
649
	mov	edi,edx
650
	ret
651
_bmove	ENDP
652
	endcode bmove
653
654
	;
655
	; Move a alligned, not overlapped, by (long) divided memory area
656
	; Args: to,from,length
657
	;
658
659
	begcode	bmove_align
660
	public	_bmove_align
661
_bmove_align	proc near
662
	fix_es	1
663
	mov	edx,edi
664
	mov	eax,esi
665
	mov	edi,P-SIZEPTR[esp]	;to
666
	mov	esi,P[esp]		;from
667
	mov	ecx,P+SIZEPTR[esp]	;length
668
	add	cx,3			;fix if not divisible with long
669
	shr	cx,2
670
	rep	movsd
671
	mov	esi,eax
672
	mov	edi,edx
673
	ret
674
_bmove_align	ENDP
675
	endcode bmove_align
676
677
	;
678
	; Move a string from higher to lower
679
	; Arg from+1,to+1,length
680
	;
681
682
	begcode	bmove_upp
683
	public	_bmove_upp
684
_bmove_upp	proc near
685
	fix_es
686
	std				; Work downward
687
	mov	edx,edi
688
	mov	eax,esi
689
	mov	edi,P-SIZEPTR[esp]	;p1
690
	mov	esi,P[esp]		;p2
691
	mov	ecx,P+SIZEPTR[esp]
692
	dec	edi			; Don't move last arg
693
	dec	esi
694
	rep	movsb			; One byte a time because overlap !
695
	cld				; C compilator wants cld
696
	mov	esi,eax
697
	mov	edi,edx
698
	ret
699
_bmove_upp ENDP
700
	endcode bmove_upp
701
702
	;
703
	; Append fillchars to string
704
	; Args: dest,len,fill
705
	;
706
707
	begcode	strappend
708
	public	_strappend
709
_strappend	proc near
710
	push	ebp
711
	mov	ebp,esp
712
	fix_es  1
713
	push	edi
714
	mov	edi,P[ebp]		; Memory pointer
715
	mov	ecx,P+SIZEPTR[ebp]	; Length
716
	clr	eax			; Find end of string
717
	repne	scasb
718
	jnz	sa_99			; String to long, shorten it
719
	movzx	eax,byte ptr P+(2*SIZEPTR)[ebp]	; Fillchar
720
	dec	edi			; Point at end null
721
	inc	ecx			; rep made one dec for null-char
722
	q_stos				; Store al in string
723
sa_99:	mov	BYTE PTR [edi],0	; End of string
724
	pop	edi
725
	pop	ebp
726
	ret
727
_strappend	ENDP
728
	endcode strappend
729
730
	;
731
	; Find if string contains any char in another string
732
	; Arg: str,set
733
	; Ret: Pointer to first found char in str
734
	;
735
736
	begcode strcont
737
	PUBLIC	_strcont
738
_strcont proc near
739
	push	ebp
740
	mov	ebp,esp
741
	fix_es	1
742
	mov	edx,edi
743
	push	esi
744
	mov	esi,P[ebp]		; str
745
	mov	ecx,P+SIZEPTR[ebp]	; Set
746
	clr	ah			; For endtest
747
	jmps	sc_60
748
749
sc_10:	scasb
750
	jz	sc_fo			; Found char
751
sc_20:	cmp	ah,[edi]		; Test if null
752
	jnz	sc_10			; Not end of set yet
753
	inc	esi			; Next char in str
754
sc_60:	mov	edi,ecx			; edi = Set
755
	mov	al,[esi]		; Test if this char exist
756
	and	al,al
757
	jnz	sc_20			; Not end of string
758
	clr	esi			; Return Null
759
sc_fo:	mov	eax,esi			; Char found here
760
	mov	edi,edx			; Restore
761
	pop	esi
762
	pop	ebp
763
	ret
764
_strcont	ENDP
765
	endcode strcont
766
767
	;
768
	; Found end of string
769
	; Arg: str
770
	; ret: Pointer to end null
771
	;
772
773
	begcode strend
774
	public	_strend
775
_strend	proc near
776
	fix_es	1
777
	mov	edx,edi			; Save
778
	mov	edi,P-SIZEPTR[esp]	; str
779
	clr	eax			; Find end of string
780
	mov	ecx,eax
781
	dec	ecx			; ECX = -1
782
	repne	scasb
783
	mov	eax,edi
784
	dec	eax
785
	mov	edi,edx			; Restore
786
	ret
787
_strend	endp
788
	endcode strend
789
790
	;
791
	; Make a string with len fill-chars and endnull
792
	; Args: dest,len,fill
793
	; Ret:  dest+len
794
	;
795
796
	begcode	strfill
797
	public	_strfill
798
_strfill proc near
799
	push	ebp
800
	mov	ebp,esp
801
	fix_es  1
802
	push	edi
803
	mov	edi,P[ebp]		; Memory pointer
804
	mov	ecx,P+SIZEPTR[ebp]	; Length
805
	movzx	eax,byte ptr P+(2*SIZEPTR)[ebp]	; Fill
806
	q_stos
807
	mov	BYTE PTR [edi],0	; End NULL
808
	mov	eax,edi			; End i DX:AX
809
	pop	edi
810
	pop	ebp
811
	ret
812
_strfill endp
813
	endcode strfill
814
815
	;
816
	; Find a char in or end of a string
817
	; Arg: str,char
818
	; Ret: pointer to found char or NullS
819
	;
820
821
	begcode strcend
822
	public	_strcend
823
_strcend proc near
824
	push	ebp
825
	mov	ebp,esp
826
	fix_es  1
827
	mov	edx,edi
828
	mov	edi,P[ebp]		; str
829
	mov	ah,P+SIZEPTR[ebp]	; search
830
	clr	al			; for scasb to find end
831
832
@@:	cmp	ah,[edi]
833
	jz	@F			; Found char
834
	scasb
835
	jnz	@B			; Not end
836
	dec 	edi			; Not found, point at end of string
837
@@:	mov	eax,edi
838
	mov	edi,edx			; Restore
839
	pop	ebp
840
	ret
841
_strcend	ENDP
842
	endcode strcend
843
844
	;
845
	; Test if string has a given suffix
846
	;
847
848
	begcode is_prefix
849
	public	_is_prefix
850
_is_prefix proc near
851
	fix_es	1
852
	mov	edx,edi			; Save edi
853
	mov	eax,esi			; Save esi
854
	mov	esi,P[esp]		; get suffix
855
	mov	edi,P-SIZEPTR[esp]	; s1
856
	push	eax			; push esi
857
	mov	eax,1			; Ok and zero-test
858
@@:	cmp	ah,[esi]
859
	jz	suf_ok			; End of string; found suffix
860
	cmpsb				; Compare strings
861
	jz	@B			; Same, possible prefix
862
	xor	eax,eax			; Not suffix
863
suf_ok:	pop	esi
864
	mov	edi,edx
865
	ret
866
_is_prefix endp
867
	endcode	_is_prefix
868
869
	;
870
	; Find a substring in string
871
	; Arg: str,search
872
	;
873
874
	begcode strstr
875
	public	_strstr
876
_strstr proc near
877
	push	ebp
878
	mov	ebp,esp
879
	fix_es	1
880
	push	EDI
881
	push	ESI
882
	mov	esi,P[ebp]		; str
883
	mov	edi,P+SIZEPTR[ebp]	; search
884
	mov	ecx,edi
885
	inc	ecx			; ECX = search+1
886
	mov	ah,[edi]		; AH = First char in search
887
	jmps	sf_10
888
889
sf_00:	mov	esi,edx			; si = Current str-pos
890
sf_10:	mov	al,[esi]		; Test if this char exist
891
	and	al,al
892
	jz	sf_90			; End of string, didn't find search
893
	inc	esi
894
	cmp	al,ah
895
	jnz	sf_10			; Didn't find first char, continue
896
	mov	edx,esi			; Save str-pos in EDX
897
	mov	edi,ecx
898
sf_20:	cmp	BYTE PTR [edi],0
899
	jz	sf_fo			; Found substring
900
	cmpsb
901
	jz	sf_20			; Char ok
902
	jmps	sf_00			; Next str-pos
903
904
sf_90:	mov	edx,1			; Return Null
905
sf_fo:	mov	eax,edx			; Char found here
906
	dec	eax			; Pointed one after
907
	pop	ESI
908
	pop	EDI
909
	pop	ebp
910
	ret
911
_strstr endp
912
	endcode strstr
913
914
	;
915
	; Find a substring in string, return index
916
	; Arg: str,search
917
	;
918
919
	begcode	strinstr
920
	public	_strinstr
921
_strinstr proc near
922
	push	ebp
923
	mov	ebp,esp
924
	push	P+SIZEPTR[ebp]		; search
925
	push	P[ebp]			; str
926
	call	_strstr
927
	add	esp,SIZEPTR*2
928
	or	eax,eax
929
	jz	si_99			; Not found, return NULL
930
	sub	eax,P[ebp]		; Pos from start
931
	inc	eax			; And first pos = 1
932
si_99:	pop	ebp
933
	ret
934
_strinstr	endp
935
	endcode strinstr
936
937
	;
938
	; Make a string of len length from another string
939
	; Arg: dst,src,length
940
	; ret: end of dst
941
	;
942
943
	begcode strmake
944
	public	_strmake
945
_strmake proc near
946
	push	ebp
947
	mov	ebp,esp
948
	fix_es	1
949
	push	EDI
950
	push	ESI
951
	mov	edi,P[ebp]		; dst
952
	mov	esi,P+SIZEPTR[ebp]	; src
953
	mov	ecx,P+SIZEPTR*2[ebp]	; Length of memory-area
954
	clr	al			; For test of end-null
955
	jcxz	sm_90			; Nothing to move, put zero at end.
956
957
@@:	cmp	al,[esi]		; Next char to move
958
	movsb				; move arg
959
	jz	sm_99			; last char, we are ready
960
	loop	@B			; Continue moving
961
sm_90:	mov	BYTE PTR [edi],al	; Set end pos
962
	inc	edi			; Fix that di points at end null
963
sm_99:	dec	edi			; di points now at end null
964
	mov	eax,edi			; Ret value in DX:AX
965
	pop	ESI
966
	pop	EDI
967
	pop	ebp
968
	ret
969
_strmake	ENDP
970
	endcode strmake
971
972
	;
973
	; Find length of string with maxlength
974
	; arg: str,maxlength
975
	; ret: length
976
	;
977
978
	begcode	strnlen
979
	public	_strnlen
980
_strnlen proc near
981
	push	ebp
982
	mov	ebp,esp
983
	fix_es	1
984
	push	edi
985
	mov	edi,P[ebp]		; Str
986
	mov	ecx,P+SIZEPTR[ebp]	; length
987
	mov	edx,edi			; Save str to calc length
988
	jcxz	sn_10			; Length = 0
989
	clr	al			; Find end of string
990
	repne	scasb			; Find strend or length
991
	jnz	sn_10
992
	dec	edi			; DI points at last null
993
sn_10:	mov	eax,edi
994
	sub	eax,edx			; Ax = length
995
	pop	edi
996
	pop	ebp
997
	ret
998
_strnlen	ENDP
999
	endcode strnlen
1000
1001
	;
1002
	; Move a string with max len chars
1003
	; arg: dst,src,len
1004
	; ret: pos to first null or dst+len
1005
1006
	begcode	strnmov
1007
	public	_strnmov
1008
_strnmov PROC near
1009
	push	ebp
1010
	mov	ebp,esp
1011
	fix_es	1
1012
	push	EDI
1013
	push	ESI
1014
	mov	edi,P[ebp]		; dst
1015
	mov	esi,P+SIZEPTR[ebp]	; src
1016
	mov	ecx,P+(SIZEPTR*2)[ebp]	; length
1017
	jcxz	snm_99			; Nothing to do
1018
	clr	al			; For test of end-null
1019
1020
@@:	cmp	al,[esi]		; Next char to move
1021
	movsb				; move arg
1022
	jz	snm_20			; last char, fill with null
1023
	loop	@B			; Continue moving
1024
	inc	edi			; Point two after last
1025
snm_20:	dec	edi			; Point at first null (or last+1)
1026
snm_99:	mov	eax,edi			; Pointer at last char
1027
	pop	ESI
1028
	pop	EDI
1029
	pop	ebp
1030
	ret
1031
_strnmov	ENDP
1032
	endcode strnmov
1033
1034
;
1035
; Zortech has this one in standard library
1036
;
1037
1038
	begcode strmov
1039
	public	_strmov
1040
_strmov proc	near
1041
	mov	ecx,esi			; Save old esi and edi
1042
	mov	edx,edi
1043
	mov	esi,P[esp]		; get source pointer (s2)
1044
	mov	edi,P-SIZEPTR[esp]	; EDI -> s1
1045
	fix_es	1
1046
@@:	mov	al,[esi]
1047
	movsb				; move arg
1048
	and	al,al
1049
	jnz	@B			; Not last
1050
	mov	eax,edi
1051
	dec	eax
1052
	mov	esi,ecx			; Restore args
1053
	mov	edi,edx
1054
	ret
1055
_strmov endp
1056
	endcode strmov
1057
1058
endif ; M_I386
1059
1060
	END