home *** CD-ROM | disk | FTP | other *** search
- (*
- STRNFST2.PAS January 19, 1987
-
- This is an updated version of the file Strngfst.Pas.
- It adds eight new routines, flipcount, posafter, poscafter,
- stripcountl, count, equal-structures, howmany, and stringup.
- StripR has been slightly modified. The documentation that
- appears below is basically the original documentation from
- February 3, 1986, with indications of what is new.
-
- This is a collection of Inline string manipulation
- routines intended for use with Turbo Pascal Version 3. They may
- work in Turbo Version 2, but I'm not sure. I wrote most of
- these, and I am a complete novice with assembly language --
- errors are possible. In addition, there are two routines,
- Flipchar and Stripchar, written by Mitch Lazarus and one routine
- taken almost directly from the Turbo manual. In all cases, the
- invaluable Inline.Com, by Dave Baldwin, created the Inline
- statements.
-
- These routines do nothing that you could not do
- perfectly well without them. The reason to use them is that
- Inline code is faster than the same things done without Inline
- code. How much faster? It depends on which routine, the nature
- of the strings you are using the routine on, and how you would
- otherwise code the procedure. In some cases, the increase in
- speed is very substantial; in others it is not. I get a little
- more specific in a few places below, but not much.
-
- The string you are manipulating is passed as an untyped
- variable parameter; it can be any string type. SwapSubstring has
- two other string parameters of type Longstring. You have to
- declare Longstring as some string type, but you can pass the
- parameters as string literals. I could not figure out how to
- pass string literals without typing the formal parameter. The
- functions generally require that Longstring be declared as
- String[255].
-
- Comments and suggestions are welcome. Leave a message
- on Robert Blacher's board, 202-547-2008.
-
-
- David Seidman
- 2737 Devonshire Pl. NW
- Washington, DC 20008
-
- The Routines:
-
- (In what follows, where I say a routine is significantly faster
- than another way of performing the function, it probably means
- you gain roughly a second or more on a thousand uses of the
- procedure, but you may gain more than that. Very significantly
- faster is better than that -- in tests on some routines, I have
- found differences of a factor of nearly 30 between the Inline
- routine and perhaps non-optimal Turbo coding.)
-
- NEW FUNCTION:
- Function PosAfter(find:longstring; var tline; after:integer):integer;
-
- This is like the Turbo POS function, except that it
- begins looking for the object string after position "after" in
- the target string "tline". If you set After to 0, PosAfter is
- identical to Pos. You can nest calls. Thus
- PosAfter('cat',tline, PosAfter('cat',tline,0) returns the
- starting position of the second instance of 'cat' in string
- Tline.
-
- Function Posc (find:char; var tst);Integer;
-
- This is just like the Turbo POS function, except that the
- Object is a character rather than a string. It is very slightly
- faster than POS used with a character object. Useful only if
- your program uses it an enormous amount.
-
- NEW FUNCTION:
- Function PosCAfter(FIND:Char; Var TST; N:Integer):Integer;
-
- PosCAfter is to PosAfter as PosC is to Pos.
-
- Procedure StripL (var tst; strp:char);
-
- Strips all leading characters strp from string tst. Probably
- significantly faster than non-Inline versions.
-
- NEW FUNCTION:
- Function StripCountL(var tst;strp:char):integer;
-
- StripCountL is just like StripL, except that it
- returns the number of characters stripped.
-
- Procedure StripR (var tst; strp:char);
-
- Strips all trailing characters strp from string tst. Slightly
- faster than optimal non-Inline coding, significantly faster than
- non-optimal coding. MODIFIED: apparently did not work well with
- strings not declared globally. Now should handle them.
-
- Procedure StripThrough (var tst; strp:char);
-
- Strips string tst from the left up to and including the first
- instance of character strp. Significantly faster than non-
- Inline.
-
- Procedure SwapSubstring (var tline; find, repl:longstring; var
- enough:boolean; limit:byte);
-
- Replaces all instances of substring Find in string Tline with
- substring Repl (except as described below). Find and Repl may be
- string literals. Repl may be shorter than, longer than, or the
- same length as Find. If Repl is null, Find is simply stripped
- from the string. Where Repl is longer than Find, the routine
- will stop replacing when the next replacement would make the
- string longer than Limit bytes. Enough returns True unless the
- routine stopped replacing for that reason, in which case it
- returns False. Longstring may be any string type.
-
- SwapSubstring is likely to be very significantly faster than
- non-Inline coding (except where Find and Repl are of equal
- length, where awkward Turbo coding will be almost as fast). The
- improvement may be largest where Repl contains Find as a
- substring, as in replacing "dog" by "doggie". SwapSubstring will
- do everything that FlipChar and StripChar (described below) will
- do, but they are slightly faster at what they do.
-
- Procedure Stupcase (var tline);
-
- String UpCase -- makes all lowercase characters in string tline
- uppercase. A very slight modification of the routine in the
- Turbo manual. Slightly faster than non-Inline coding.
-
- NEW FUNCTION:
-
- Function Stringup(var tline):longstring;
-
- StringUp is just like Stupcase, except that it returns
- the upper cased string as the function result and leaves the
- parameter unaltered.
-
- Procedure LowCase (var tline);
-
- Makes all uppercase characters in string Tline lowercase. An
- obvious modification of Stupcase. Depending on how you would do
- this in Turbo, could be very significantly faster. (For i := 1
- to length(tline) do if tline[i] in [A..Z] is very slow, but if
- tline[i] >= 'A' and tline[i] <='Z' is faster.)
-
- Procedure FlipChar (var tst; srch, repl:char);
-
- Replaces all instances of character scrch in string tst with
- char repl. May be very significantly faster than alternative
- coding; slightly faster than SwapSubstring.
-
- NEW FUNCTION:
- Function FlipCount(var tst;srch,repl:char):integer;
-
- Just like FlipChar, except that it returns as the function
- result the number of times it did the replacement.
-
- Procedure StripChar(var tst; strp:char);
-
- Strips out all instances of character Strp from string tst.
- Very significantly faster than non-Inline coding, slightly faster
- than SwapSubstring.
-
- NEW FUNCTION:
- Function Count (var tst; srch:char):integer;
-
- Returns the number of instances of srch in string tst. Does
- not alter the string.
-
- NEW FUNCTION
- Function HowMany(var str1,str2):integer;
-
- Compares two strings character by character up to the length
- of the shorter one. Returns the number of characters before the
- first time the characters are different.
-
- NEW FUNCTION:
- Function Equal_Structures(var a,b;size:integer):boolean;
-
- This is not exactly a string function. It compares two
- structures of size bytes. Returns true of they are equal, false
- if they are not. Useful for comparing parts of strings. For
- example, if you are reading strings of length >3 and want to
- see if they begins with 'cat', set str1 := 'cat'; and then
- compare for equality with str2 this way:
- equal_structures(str1[1],str2[1],length(str1))
-
- A slightly incorrect version of this function was included in
- Longint.arc, I collection of routines for manipulating long
- integers. That one words only if size is one more than the
- number of bytes to compare.
-
-
- *)
- Function PosAfter(find:longstring; var tline; after:integer):integer;
- begin
- Inline(
- {;INLINE code for Function}
- {; PosAfter(find:longstring;var tline; after:integer):integer;}
- {;tline is a string of any type. Find is string of}
- {;type longstring, but may be literal (e.g., 'abc','').}
- {;Longstring must be string[255].}
- {;Find may be any string type if compiler set appropriately}
- {;finds first instance of find after tline[after] }
- {;Returns zero if not found, otherwise the position find starts in}
- $1E { push ds}
- /$8A/$96/>FIND { mov dl, [>find[bp]] ;store length of find}
- /$8A/$86/>FIND+$0001 { mov al,[>find[bp]+1] ;store first find character in al}
- /$C7/$86/$0A/$01/$00/$00 { mov wo[bp+266],0 ;result of no match}
- /$C4/$BE/>TLINE { les di, >tline[BP] ;address of string to modify}
- /$8C/$C3 { mov bx,es ;match segments}
- /$8E/$DB { mov ds,bx}
- /$31/$C9 { xor cx,cx ;zero out cx}
- /$8A/$0D { mov cl,[di] ;length tline to cl}
- /$E3/$2E { jcxz quit ;exit if tline null}
- /$89/$CB { mov bx,cx ;save length}
- /$2B/$8E/>AFTER { sub cx, >after[bp]}
- /$7E/$26 { jle quit}
- /$03/$BE/>AFTER { add di, >after[bp] ;move to char to begin after}
- /$47 {j2: inc di ;to after it}
- /$38/$D1 {scan: cmp cl, dl ;is remaining string>find?}
- /$72/$1D { jb quit ;exit if not enough left for a match}
- /$FC { cld ;move forwards}
- /$F2/$AE {repne scasb ;search for first char}
- /$75/$18 { jne quit ;exit if not found}
- /$51 { push cx ;save no. of bytes left after match}
- /$4F { dec di ;to match position}
- /$57 { push di ;save position after match}
- /$8D/$B6/>FIND+$0001 { lea si, >find[bp]+1}
- /$88/$D1 { mov cl, dl ;get length of find string}
- /$F3/$36/$A6 {repe ss:cmpsb ;match on find string?}
- /$5F { pop di ;start of match test}
- /$59 { pop cx ;bytes then remaining}
- /$75/$E6 { jne j2 ;cycle if no match}
- {;gets here if you found a match. }
- /$F7/$D9 { neg cx ;negative start}
- /$01/$D9 { add cx,bx ;add new and old length}
- /$89/$8E/$0A/$01 { mov [bp+266],cx ;}
- /$1F {quit: pop ds}
- );
- end;
-
- (*--------------------------------------------------*)
- function posc(find:char;var tst):integer;
- begin
- Inline(
- {;code for posc -- a single character version of pos}
- $1E { push ds ;initialize}
- /$C4/$BE/>TST { les di,>tst[bp] ;get string length}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$C7/$46/$0A/$00/$00 { mov wo [bp+10],0 ;result if nothing found or }
- { ; length 0}
- /$8A/$86/>FIND { mov al,>find[bp] ;get the character}
- /$29/$C9 { sub cx,cx}
- /$8A/$0D { mov cl,[di] ;get length}
- /$E3/$0D { jcxz quit ;stop if zero length}
- /$89/$CB { mov bx,cx ;save length}
- /$47 { inc di ;start at first char}
- /$FC { cld ;moveforward}
- /$F2/$AE {repne scasb}
- /$75/$05 { jne quit ;stop if not found}
- /$29/$CB { sub bx,cx ;add new and old length}
- /$89/$5E/$0A { mov [bp+10],bx ;save result}
- /$1F {quit: pop ds}
- );
- end;
-
- (*--------------------------------------------------*)
- Function PosCAfter(FIND:Char; Var TST; N:Integer):Integer;
- {returns the location of the first character Find in string Tst
- after position N in the string. Returns zero if not found.
- To find, e.g., the second instance of Find, replace N by another
- call to the function, with N = 0
- Written by D. Seidman, 6/28/86}
-
- begin
- Inline(
- $1E { push ds ;initialize}
- /$C4/$BE/>TST { les di,>tst[bp] ;load string}
- /$C7/$46/$0C/$00/$00 { mov wo [bp+12],0 ;result if nothing found or }
- { ; start beyond length}
- /$8A/$86/>FIND { mov al,>find[bp] ;get the character}
- /$31/$C9 { xor cx,cx}
- /$8A/$0D { mov cl,[di] ;get length}
- /$E3/$19 { jcxz quit ;stop if zero length}
- /$89/$CB { mov bx,cx ;save length}
- /$2B/$8E/>N { sub cx,>N[bp] ;length after start}
- /$7E/$11 { jle quit ;quit if nowhere to search}
- /$03/$BE/>N { add di,>N[bp] ;moves to the char to begin after}
- /$47 { inc di ;to after it}
- /$FC { cld ;moveforward}
- /$F2/$AE {repne scasb ;search}
- /$75/$07 { jne quit ;stop if not found}
- /$F7/$D9 { neg cx}
- /$01/$D9 { add cx,bx ;add new and old length}
- /$89/$4E/$0C { mov [bp+12],cx ;save result}
- /$1F {quit: pop ds}
- );
- end;
- (*--------------------------------------------------*)
-
- Procedure StripL (Var tst; strp:char);
- Begin
- Inline(
- {;procedure StripL (var tst; strp:char)}
- {;Code for inline, Turbo 3.}
- {;deletes leading character strp from string tst}
- {;tst may be of any string type.}
- {;modified 1/30/86}
- {;written by D. Seidman}
- $1E { push ds ; save for exit}
- /$C4/$BE/>TST { les di,>tst[bp] ; ES:DI to start}
- /$8C/$C0 { mov ax,es ; match segments}
- /$8E/$D8 { mov ds,ax}
- /$89/$FB { mov bx,di ; save start}
- /$8A/$86/>STRP { mov al,>strp[bp] ; char to strip}
- /$29/$C9 { sub cx,cx ; zero in CX}
- /$8A/$0D { mov cl,[di] ; length in CX}
- /$E3/$17 { jcxz quit ; exit if null}
- /$47 { inc di}
- /$3A/$05 { cmp al,[di] ; check first char}
- /$75/$12 { jne quit ; exit if no match}
- /$47 { inc di ; next char}
- /$49 { dec cx ; already checked first one}
- /$FC { cld ; frontwards}
- /$F3/$AE {repe scasb ; do search after first}
- /$74/$07 { je null ; if stripping whole line}
- /$89/$FE { mov si,di ; char after last match}
- /$89/$DF { mov di,bx ; to start of string}
- /$47 { inc di}
- /$4E { dec si ; }
- /$41 { inc cx}
- /$89/$0F {null: mov [bx],cx ; to get length right}
- /$F2/$A4 {rep movsb ; delete}
- /$1F {quit: pop ds}
- );
- end;
-
- (*------------------------------------------------*)
- function StripCountL(var tst;strp:char):integer;
- begin
- Inline(
- {;Function StripCountL (var tst; strp:char):integer;}
- {;Code for inline, Turbo 3.}
- {;deletes leading character strp from string tst}
- {;tst may be of any string type.}
- {;returns the number of characters stripped}
- {;written by D. Seidman, 2/16/86}
- $1E { push ds ; save for exit}
- /$C4/$BE/>TST { les di,>tst[bp] ; ES:DI to start}
- /$8C/$C0 { mov ax,es ; match segments}
- /$8E/$D8 { mov ds,ax}
- /$89/$FB { mov bx,di ; save start}
- /$8A/$86/>STRP { mov al,>strp[bp] ; char to strip}
- /$29/$C9 { sub cx,cx ; zero in CX}
- /$8A/$0D { mov cl,[di] ; length in CX}
- /$89/$CA { mov dx,cx ; save original length}
- /$C7/$46/$0A/$00/$00 { mov wo [bp+10],0 ; set result of zero}
- /$E3/$1C { jcxz quit ; exit if null}
- /$47 { inc di}
- /$3A/$05 { cmp al,[di] ; check first char}
- /$75/$17 { jne quit ; exit if no match}
- /$47 { inc di ; next char}
- /$49 { dec cx ; already checked first one}
- /$FC { cld ; frontwards}
- /$F3/$AE {repe scasb ; do search after first}
- /$74/$07 { je null ; if stripping whole line}
- /$89/$FE { mov si,di ; char after last match}
- /$89/$DF { mov di,bx ; to start of string}
- /$47 { inc di}
- /$4E { dec si ; }
- /$41 { inc cx}
- /$89/$0F {null: mov [bx],cx ; to get length right}
- /$29/$CA { sub dx,cx ;number of bytes stripped}
- /$89/$56/$0A { mov [bp+10],dx ;move that to function result}
- /$F2/$A4 {rep movsb ; delete}
- /$1F {quit: pop ds}
- );
- end;
-
- (*------------------------------------------------*)
- Procedure StripR(Var tst; strp:char);
- begin
- Inline(
- {;Creates procedure StripR (var tst;strp:char)}
- {;Strips trailing characters strp from string tst.}
- {;tst may be any string type.}
- {;modified 2/16/86. D. Seidman}
- $1E { push ds}
- /$C4/$BE/>TST { les di,>tst[bp] ; ES:DI to start}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$89/$FB { mov bx,di ; save start}
- /$8A/$86/>STRP { mov al,>strp[bp]; char to strip}
- /$29/$C9 { sub cx,cx ; zero CX}
- /$8A/$0D { mov cl,[di] ; length in CX}
- /$E3/$0E { jcxz quit ; exit if null}
- /$01/$CF { add di,cx ;start at far end of string}
- /$3A/$05 { cmp al,[di] ;check last character}
- /$75/$08 { jne quit ;exit if no match}
- /$FD { std ;scan backwards}
- /$F3/$AE {repe scasb ;search for first non-matching byte}
- /$74/$01 { je null ;if you are stripping all characters}
- /$41 { inc cx ;fix length}
- /$88/$0F {null: mov [bx],cl ;new length}
- /$1F {quit: pop ds}
- );
-
- end;
-
-
- (*----------------------------------------------*)
-
- Procedure StripThrough (Var tst; strp:char);
- Begin
- Inline(
- {;Creates Procedure StripThrough (var tst;strp:char)}
- {;With string tst and char strp, it}
- {;strips from the left up to and including}
- {;the first instance of char strp}
- {;modified 1/30/86. D. Seidman}
- $1E { push ds}
- /$C4/$BE/>TST { LES DI,>TST[BP] ; ES:DI to start}
- /$89/$FB { MOV BX,DI ; save start}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$8A/$86/>STRP { MOV AL,>STRP[BP] ; char to strip through}
- /$29/$C9 { SUB CX,CX ; zero in CX}
- /$8A/$0D { MOV CL,[DI] ; length in CX}
- /$E3/$0F { JCXZ QUIT ; exit if null}
- /$47 { INC DI ; first char}
- /$FC { CLD ; frontwards}
- /$F2/$AE {REPNE SCASB ; do search}
- /$75/$09 { JNE QUIT ; not found}
- /$89/$FE { MOV SI,DI ; char after, start move here}
- /$89/$DF { MOV DI,BX}
- /$47 { INC DI }
- /$89/$0F { MOV [BX],cx ; to get length right}
- /$F2/$A4 {REP MOVSB ; delete leading characters}
- /$1F {QUIT: pop ds}
- );
- end;
-
- (*----------------------------------------------*)
-
- Procedure SwapSubstring (Var tline; find, repl:longstring;
- Var enough:boolean; limit:byte);
- begin
- Inline(
- {;tline is a string of any type. Find and replace are strings of}
- {;type longstring, but may be literals (e.g., 'abc','').}
- {;Longstring may be any string type.}
- {;Replaces all instances of substring find with substring repl in tline.}
- {;Limit is the maximum permissible length of the string Tline}
- {;after the replacements. It should be no greater than the}
- {;size of tline's type, but it may be shorter.}
- {;Enough returns FALSE if not all swaps are accomplished}
- {;because limit length exceeded.}
- {;If limit is less than the actual length of tline and repl is longer}
- {;than find, no replacements are done. If limit is longer than}
- {;length tline and repl is longer than find, replaces are done up to}
- {;the point where the next replace would leave tline longer than limit.}
- {;If repl is not longer than find, limit has no effect.}
- $1E { push ds}
- /$8A/$96/>FIND { mov dl, [>find[bp]] ;store length of find}
- /$8A/$86/>FIND+$0001 { mov al,[>find[bp]+1] ;store first find character in al}
- /$8A/$B6/>REPL { mov dh,[>repl[bp]] ;store length of repl}
- /$88/$D4 { mov ah, dl}
- /$28/$F4 { sub ah,dh ;find difference in length of strings}
- /$C4/$BE/>ENOUGH { les di,>enough[bp] ;initialize flag}
- /$C6/$05/$01 { mov by [di],1}
- /$C4/$BE/>TLINE { les di, >tline[BP] ;address of string to modify}
- /$8C/$C3 { mov bx,es ;match segments}
- /$8E/$DB { mov ds,bx}
- /$89/$FB { mov bx,di ;save tline address}
- /$31/$C9 { xor cx,cx ;zero out cx}
- /$8A/$0D { mov cl,[di] ;length tline to cl}
- /$E3/$03 { jcxz j1 ;exit if tline null}
- /$E9/$03/$00 { jmp j2}
- /$E9/$8E/$00 {j1: jmp quit}
- /$47 {j2: inc di ;to start of string}
- /$38/$D1 {scan: cmp cl, dl ;is remaining string>find?}
- /$72/$F8 { jb j1 ;exit if not enough left for a match}
- /$FC { cld ;move forwards}
- /$F2/$AE {repne scasb ;search for first char}
- /$75/$F3 { jne j1 ;exit if not found}
- /$51 { push cx ;save no. of bytes left after match}
- /$4F { dec di ;to match position}
- /$57 { push di ;save position after match}
- /$8D/$B6/>FIND+$0001 { lea si, >find[bp]+1}
- /$88/$D1 { mov cl, dl ;get length of find string}
- /$F3/$36/$A6 {repe ss:cmpsb ;match on find string?}
- /$5F { pop di ;start of match test}
- /$59 { pop cx ;bytes then remaining}
- /$75/$E6 { jne j2 ;cycle if no match}
- {;gets here if you found a match. Now compare find and replace strings}
- /$FE/$C1 { inc cl ;bytes from beginning of match}
- /$80/$FC/$00 { cmp ah,0 ;test which branch to follow}
- /$74/$52 { je moveq ;skip string adjust if find=repl}
- /$7C/$1B { jl longrep ;jump if repl >find}
- {;if find > repl, need to close up the gap resulting from replacing}
- /$28/$D1 { sub cl,dl ;no of bytes from end of find string}
- /$51 { push cx ;save it}
- /$57 { push di ;save beginning of match}
- /$89/$FE { mov si, di ;make both start of match}
- /$53 { push bx ;clear some workspace}
- /$31/$DB { xor bx, bx ; " }
- /$88/$F3 { mov bl, dh ;len(repl) }
- /$01/$DF { add di, bx ;add to get destination address}
- /$88/$D3 { mov bl, dl ;len(find)}
- /$01/$DE { add si, bx ;add to get source address}
- /$5B { pop bx ;restore}
- /$28/$27 { sub [bx],ah ;shrink tline[0]}
- /$F2/$A4 {rep movsb ;close the gap}
- /$5F { pop di ;get back start of match}
- /$59 { pop cx ;get back bytes after replacing}
- /$E9/$37/$00 { jmp movr ;go do the replacement}
- {;if repl> find, increase the gap }
- /$57 {longrep: push di }
- {;test whether this would make string too long}
- /$F6/$DC { neg ah}
- /$52 { push dx ;get some workspace}
- {;if you do not like using the parameter limit, you can fix }
- {;the limit by replacing the following line with the commented}
- {;line after it. Then you can replace 255 with whatever length less}
- {;than that you want.}
- /$8A/$B6/>LIMIT { mov dh,[>limit[bp]] ;get maximum string length}
- {; mov dh,255 ;get max string length}
- /$28/$E6 { sub dh,ah ;find longest string you can add to}
- /$8A/$17 { mov dl,[bx] ;get actual current length}
- /$38/$F2 { cmp dl,dh ;compare them}
- /$77/$37 { ja j5 ;stop if max<actual, but pop first}
- /$5A { pop dx ;restore}
- /$00/$27 { add by [bx],ah ;increase string length}
- {;now need to make room for the replace}
- /$53 { push bx ;save tline address}
- /$02/$1F { add bl,[bx] ;get end of tline}
- /$73/$02 { jnc j4}
- /$FE/$C7 { inc bh ;add one if a carry}
- /$89/$DF {j4: mov di,bx ;move to end of lengthened string}
- {;now need where you are moving it too}
- /$31/$DB { xor bx,bx ;clear some space}
- /$88/$E3 { mov bl,ah ;get the increment}
- /$89/$FE { mov si,di ;move the address}
- /$29/$DE { sub si,bx ;get end of string before increment}
- /$5B { pop bx ;restore}
- /$51 { push cx ;save bytes after first match}
- /$28/$D1 { sub cl,dl ;don't move bytes in find}
- /$FD { std ;change direction}
- /$F2/$A4 {rep movsb ;move the string down}
- /$FC { cld ;get the direction again}
- /$59 { pop cx ;restore}
- /$5F { pop di ;restore.}
- /$28/$D1 { sub cl,dl ;subtract find from remaining bytes}
- /$F6/$DC { neg ah}
- /$E9/$02/$00 { jmp movr ;go get the replace}
- {;now fix up cx for equal strings}
- /$28/$F1 {moveq: sub cl,dh ;bytes remaining after repl}
- {;now move repl into place}
- /$51 {movr: push cx ;save bytes remaining}
- /$8D/$B6/>REPL+$0001 { lea si, [>repl[bp]+1] ;get replace string}
- /$31/$C9 { xor cx,cx ;clear it out}
- /$88/$F1 { mov cl,dh ;get bytes to move- len(repl)}
- /$F2/$36/$A4 {rep ss:movsb ;move replacement string}
- /$59 { pop cx ;bytes remaining.di should be ok}
- /$E9/$7C/$FF { jmp near scan ;look for next match}
- /$5A {j5: pop dx ;clean up stack}
- /$C4/$BE/>ENOUGH { les di, >enough[bp] ;not enough to make all swaps}
- /$C6/$05/$00 { mov by [di],0}
- /$5F { pop di}
- /$1F {quit: pop ds}
- );
- end;
-
- (*----------------------------------------------*)
-
- procedure stupcase(var tline);
- {uppercases the lower case letters in tline.
- based on routine in Turbo manual, slightly modified}
-
- begin
- Inline(
- $1E { push ds}
- /$C4/$BE/>TLINE { les di, >tline[bp]}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$8A/$0D { mov cl,[di]}
- /$FE/$C1 { inc cl}
- /$FE/$C9 {l1: dec cl}
- /$74/$10 { jz l2}
- /$47 { inc di}
- /$80/$3D/$61 { cmp by[di],'a'}
- /$72/$F6 { jb l1}
- /$80/$3D/$7A { cmp by[di],'z'}
- /$77/$F1 { ja l1}
- /$80/$2D/$20 { sub by[di],$20}
- /$EB/$EC { jmp short l1}
- /$1F {l2: pop ds}
- );
- end;
-
- (*---------------------------------------*)
- Function Stringup(var tline):longstring;
-
- (*--------------------------*)
- {
- Function result is all-uppercase
- version of string tline. Written
- by D. Seidman, 1/5/87. Longstring is
- any string type.
- }
- (*--------------------------*)
-
- Begin
- Inline(
- {;Function stringup(var tline):longstring;}
- $1E { push ds ;save things for later}
- /$C5/$B6/>TLINE { lds si, >tline[bp] ;addressing of the string}
- /$8C/$D0 { mov ax,ss ;addessing of the destination}
- /$FC { cld ;move forward}
- /$8E/$C0 { mov es,ax}
- /$31/$C9 { xor cx,cx}
- /$8A/$0C { mov cl,[si] ;string length to cl}
- /$8D/$7E/$08 { lea di, [bp+8] ;point di to function result}
- /$26/$88/$0D { es: mov [di],cl ;and move length to function result}
- /$46 { inc si ;point to start of string}
- /$47 { inc di ;and where it goes}
- /$AC {l1: lodsb ;get byte from string}
- /$3C/$61 { cmp al,'a' ;tests from Turbo manual}
- /$72/$06 { jb l3}
- /$3C/$7A { cmp al,'z'}
- /$77/$02 { ja l3}
- /$2C/$20 { sub al,$20}
- /$AA {l3: stosb ;store result}
- /$E2/$F2 { loop l1}
- /$1F {l2: pop ds}
- );
- end;
- (*----------------------------------------------*)
-
- procedure lowcase(var tline);
- {converts all upper case letters in tline to lowercase
- slightly modified from routine in Turbo manual}
-
- begin
- Inline(
- $1E { push ds}
- /$C4/$BE/>TLINE { les di, >tline[bp]}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$8A/$0D { mov cl,[di]}
- /$FE/$C1 { inc cl}
- /$FE/$C9 {l1: dec cl}
- /$74/$10 { jz l2}
- /$47 { inc di}
- /$80/$3D/$41 { cmp by[di],'A'}
- /$72/$F6 { jb l1}
- /$80/$3D/$5A { cmp by[di],'Z'}
- /$77/$F1 { ja l1}
- /$80/$05/$20 { add by[di],$20}
- /$EB/$EC { jmp short l1}
- /$1F {l2: pop ds}
- );
- end;
-
- (*----------------------------------------------*)
-
-
- procedure flipchar(var tst; srch, repl: char);
- (*
- CALL AS FLIPCHAR(VAR INSTRING; CH1, CH2: CHAR),
- CHANGES EACH OCCURRENCE OF CH1 IN INSTRING TO CH2.
- *)
- begin;
- Inline(
- $C4/$BE/>TST { LES DI,>TST[BP] ; ES:DI to start}
- /$8A/$86/>SRCH { MOV AL,>SRCH[BP] ; search char}
- /$8A/$A6/>REPL { MOV AH,>REPL[BP] ; repl. char}
- /$29/$C9 { SUB CX,CX ; zero in CX}
- /$8A/$0D { MOV CL,[DI] ; length in CX}
- /$E3/$0D { JCXZ QUIT ; exit if null}
- /$47 { INC DI ; first char}
- /$FC { CLD ; frontwards}
- /$E3/$09 {MORE: JCXZ QUIT ; no more}
- /$F2/$AE {REPNE SCASB ; do search}
- /$75/$05 { JNE QUIT ; not found}
- /$88/$65/$FF { MOV [DI-1],AH ; replace}
- /$EB/$F5 { JMP MORE ; try for more}
- /$90 {QUIT: NOP ; exit}
- );
- end;
-
- (*----------------------------------------------*)
- function flipcount(var tst;srch,repl:char):integer;
-
- (* Tst is a string. This is identical to the procedure
- Flipchar except that the function returns the number of
- times the search character was replaced by the find character.
- Written 2/16/86 by D. Seidman, based on Flipchar by M. Lazarus*)
-
- begin
- Inline(
- $1E { PUSH ds}
- /$C4/$BE/>TST { LES DI,>TST[BP] ; ES:DI to start}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$8A/$86/>SRCH { MOV AL,>SRCH[BP] ; search char}
- /$8A/$A6/>REPL { MOV AH,>REPL[BP] ; repl. char}
- /$29/$DB { sub bx,bx ;zero in bx -- for counting}
- /$29/$C9 { SUB CX,CX ; zero in CX}
- /$8A/$0D { MOV CL,[DI] ; length in CX}
- /$E3/$0E { JCXZ QUIT ; exit if null}
- /$47 { INC DI ; first char}
- /$FC { CLD ; frontwards}
- /$E3/$0A {MORE: JCXZ QUIT ; no more}
- /$F2/$AE {REPNE SCASB ; do search}
- /$75/$06 { JNE QUIT ; not found}
- /$43 { inc bx ;count it}
- /$88/$65/$FF { MOV [DI-1],AH ; replace}
- /$EB/$F4 { JMP MORE ; try for more}
- /$89/$5E/$0C {QUIT: mov [bp+12],bx ;get function result}
- /$1F { pop ds}
- );
- end;
-
- (*----------------------------------------------*)
-
- procedure stripchar(var tst; strp: char);
- (*
- CALL AS STRIPCHAR(VAR INSTRING; CH: CHAR),
- REMOVES EACH OCCURRENCE OF CH IN INSTRING.
- *)
- begin;
- Inline(
- $1E { PUSH DS ; save for exit}
- /$C4/$BE/>TST { LES DI,>TST[BP] ; ES:DI to start}
- /$89/$FB { MOV BX,DI ; save start}
- /$8C/$C0 { MOV AX,ES ; match segments}
- /$8E/$D8 { MOV DS,AX ; (same)}
- /$8A/$86/>STRP { MOV AL,>STRP[BP] ; char to strip}
- /$29/$C9 { SUB CX,CX ; zero in CX}
- /$8A/$0D { MOV CL,[DI] ; length in CX}
- /$E3/$16 { JCXZ QUIT ; exit if null}
- /$47 { INC DI ; first char}
- /$FC { CLD ; frontwards}
- {MORE:}
- /$F2/$AE {REPNE SCASB ; do search}
- /$75/$10 { JNE QUIT ; not found}
- /$57 { PUSH DI ; save locn}
- /$51 { PUSH CX ; bytes to go}
- /$89/$FE { MOV SI,DI ; char after}
- /$4F { DEC DI ; destination}
- /$F2/$A4 {REP MOVSB ; delete}
- /$FE/$0F { DEC BY [BX] ; decr length}
- /$59 { POP CX ; bytes to go}
- /$5F { POP DI ; last locn}
- /$4F { DEC DI ; char gone}
- /$E3/$02 { JCXZ QUIT ; no more}
- /$EB/$EC { JMP MORE ; try again}
- /$1F {QUIT: POP DS ; restore for exit}
- );
- end;
- (*----------------------------------------------*)
- Function Count (var tst; srch:char):integer;
- begin
- Inline(
- {;Function Count(var tst; srch:char):integer}
- {;Returns count of instances of srch in string tst}
- $1E { PUSH ds}
- /$C4/$BE/>TST { LES DI,>TST[BP] ; ES:DI to start}
- /$8C/$C0 { mov ax,es}
- /$8E/$D8 { mov ds,ax}
- /$8A/$86/>SRCH { MOV AL,>SRCH[BP] ; search char}
- /$29/$DB { sub bx,bx ;zero in bx -- for counting}
- /$29/$C9 { SUB CX,CX ; zero in CX}
- /$8A/$0D { MOV CL,[DI] ; length in CX}
- /$E3/$0B { JCXZ QUIT ; exit if null}
- /$47 { INC DI ; first char}
- /$FC { CLD ; frontwards}
- /$E3/$07 {MORE: JCXZ QUIT ; no more}
- /$F2/$AE {REPNE SCASB ; do search}
- /$75/$03 { JNE QUIT ; not found}
- /$43 { inc bx ;count it}
- /$EB/$F7 { JMP MORE ; try for more}
- /$89/$5E/$0A {QUIT: mov [bp+10],bx ;get function result}
- /$1F { pop ds}
- );
- end;
- (*----------------------------------------------*)
- Function HowMany (var str1,str2): integer;
- begin
- Inline(
- {;Function HowMany(var str1,str2):integer;}
- {;str1 and str2 are strings of any type.}
- {;function compares them character by}
- {;character for up to min(length(str1),length(str2))}
- {;characters. Function is the number of consecutive}
- {;characters (starting with string 1) for which the}
- {;two strings are equal. e.g., if str1 is cats and}
- {;str2 is catchup, function result is 3. If str1 is}
- {;cat and str2 is dog, function result is 0.}
- $1E { push ds}
- /$C5/$B6/>STR1 { lds si, >str1[bp] ;addressing str1}
- /$C4/$BE/>STR2 { les di, >str2[bp] ;addressing str2}
- /$31/$C9 { xor cx,cx ;zero cx}
- /$8A/$0D { mov cl,[di] ;get length str2}
- /$3A/$0C { cmp cl,[si] ;compare lengths}
- /$72/$02 { jb diless}
- /$8A/$0C {siless: mov cl, [si]}
- /$89/$CB {diless: mov bx, cx ;save length}
- /$FC { cld ;move forward}
- /$46 { inc si ;to start of string}
- /$47 { inc di ; "}
- /$F3/$A6 {repe cmpsb ;string compare}
- /$74/$01 { je j1 ;equal for full length}
- /$41 { inc cx ;correct, last byte ne}
- /$29/$CB {j1: sub bx,cx ;# matching bytes}
- /$89/$5E/$0C { mov [bp+12],bx ;function result}
- /$1F { pop ds}
- );
- end;
-
- (*----------------------------------------------*)
- Function Equal_Structures(var a,b;size:integer):boolean;
-
- {compares two structures of size bytes. Returns
- true of they are equal, false if they are not.
- Written by D. Seidman. This revision 12/27/86}
-
-
- begin
- Inline(
- $1E { push ds}
- /$C6/$46/$0E/$01 { mov by [bp+14],1 ;set up a true result}
- /$C4/$BE/>A { les di,>a[bp] ;get first structure, es:di}
- /$C5/$B6/>B { lds si,>b[bp] ;get second structure, ds:si}
- /$8B/$8E/>SIZE { mov cx,>size[bp] ;get length of structures}
- /$F3/$A6 {repe cmpsb ;compare, byte by byte}
- /$74/$04 { je quit ;if still equal, done}
- /$C6/$46/$0E/$00 { mov by [bp+14],0 ;set result for unequal}
- /$1F {quit: pop ds}
- );
- end;
- (*----------------------------------------------*)
-
-