home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 436_01 / stringz.asm < prev    next >
Encoding:
Assembly Source File  |  1994-10-07  |  35.5 KB  |  897 lines

  1. ;==========================================================================
  2. ;   STRINGZ.ASM
  3. ;
  4. ; C-callable routines that offer string handling capabilities similar
  5. ; to those found in BASIC, and then some.
  6. ;
  7. ; None of the routines in this file allocate memory for, or check for
  8. ; overflow in copying to, destination strings.  It is the responsibility
  9. ; of the calling routine to insure that enough space is available for
  10. ; the destination strings, including terminating null bytes.
  11. ;
  12. ;    Assembler:     Borland TASM 1.01 (tasm /ml/t/w2/z stringz;)
  13. ;
  14. ; INCON source files and the object and library files created from
  15. ; them are:
  16. ;    Copyright (c) 1993-94, Richard Zigler.
  17. ; You may freely distribute unmodified source, object, and library
  18. ; files, and incorporate them into your own non-commercial software,
  19. ; provided that this paragraph and the copyright string defined in
  20. ; INCON.C are included in all copies.
  21. ;==========================================================================
  22. ; Function Prototypes
  23. ;
  24. ; The string pointer and function return types are all declared
  25. ; "far", so that these routines can be linked with programs under
  26. ; any memory model.  The functions in this source file can handle
  27. ; strings up to 32,767 bytes long.
  28. ;
  29. ; char far * pascal far LeftStr  ( char far *, char far *, short         );
  30. ; char far * pascal far RightStr ( char far *, char far *, short         );
  31. ; char far * pascal far MidStr   ( char far *, char far *, short, short  );
  32. ; char far * pascal far lJust    ( char far *, char far *, short, short  );
  33. ; char far * pascal far rJust    ( char far *, char far *, short, short  );
  34. ; char far * pascal far cJust    ( char far *, char far *, short, short  );
  35. ; char far * pascal far lTrim    ( char far *, char far *                );
  36. ; char far * pascal far rTrim    ( char far *, char far *                );
  37. ; char far * pascal far ReplStr  ( char far *, char far *, short, short  );
  38. ; char far * pascal far InsStr   ( char far *, char far *, short, short  );
  39. ; char far * pascal far TemplStr ( char far *, char far *, short         );
  40. ;==========================================================================
  41.  
  42.          locals                         ;enable TASM local symbols
  43.           model     small, pascal       ;set PASCAL stack handling
  44.  
  45. ;--------------------------------------------------------------------------
  46. ; Macros to push registers at entry and pop registers at exit.
  47. ;--------------------------------------------------------------------------
  48.  
  49.       @PushRegs     macro reglist
  50.            ifnb     <reglist>
  51.             irp     reg, <reglist>
  52.            push     reg
  53.            endm
  54.           endif
  55.                     endm
  56.  
  57.        @PopRegs     macro reglist
  58.            ifnb     <reglist>
  59.             irp     reg, <reglist>
  60.             pop     reg
  61.            endm
  62.           endif
  63.                     endm
  64.  
  65.           .code
  66.  
  67. ;--------------------------------------------------------------------------
  68. ;       LeftStr
  69. ;
  70. ; Copies Num characters from left end of SrcStr to DestStr; returns
  71. ; pointer to DestStr.
  72. ;
  73. ; If Num is greater than or equal to the length of SrcStr, all of
  74. ; SrcStr is copied.  If Num is outside the range 1 to 32767, DestStr
  75. ; is returned null.
  76. ;--------------------------------------------------------------------------
  77.  
  78.          public     LEFTSTR
  79.         LEFTSTR     proc far
  80.  
  81.             arg     Num       :word               ;characters to copy
  82.             arg     SrcStr    :far ptr byte       ;source string
  83.             arg     DestStr   :far ptr byte       ;destination string
  84.  
  85.      ParmSize =     type Num + type SrcStr + type DestStr
  86.  
  87.       @PushRegs     <si, di, ds>
  88.             mov     dx, ParmSize
  89.             les     di, [DestStr]
  90.            call     NullPtr
  91.             mov     dx, es              ;save for return
  92.             mov     bx, di
  93.             mov     ax, [Num]           ;# chars to move
  94.             and     ax, ax
  95.             jle     @@Term
  96.             lds     si, [SrcStr]
  97.            call     StrLen              ;CX = source length
  98.             cmp     cx, ax
  99.             jle     @@Move
  100.             mov     cx, ax
  101. @@Move:
  102.       rep movsb
  103. @@Term:
  104.             sub     al, al
  105.           stosb
  106.             mov     ax, bx              ;DX:AX->DestStr
  107.        @PopRegs     <ds, di, si>
  108.             ret
  109.         LEFTSTR     endp
  110.  
  111. ;--------------------------------------------------------------------------
  112. ;      RightStr
  113. ;
  114. ; Copies Num characters from right end of SrcStr to DestStr; returns
  115. ; pointer to DestStr.
  116. ;
  117. ; If Num is greater than or equal to the length of SrcStr, all of
  118. ; SrcStr is copied.  If Num is outside the range 1 to 32767, DestStr
  119. ; is returned null.
  120. ;--------------------------------------------------------------------------
  121.  
  122.          public     RIGHTSTR
  123.        RIGHTSTR     proc far
  124.  
  125.             arg     Num       :word               ;characters to copy
  126.             arg     SrcStr    :far ptr byte       ;source string
  127.             arg     DestStr   :far ptr byte       ;destination string
  128.  
  129.      ParmSize =     type Num + type SrcStr + type DestStr
  130.  
  131.       @PushRegs     <si, di, ds>
  132.             mov     dx, ParmSize
  133.             les     di, [DestStr]
  134.            call     NullPtr
  135.            push     es                  ;save for return
  136.            push     di
  137.             lds     si, [SrcStr]
  138.            call     StrLen              ;CX = source length
  139.             and     cx, cx
  140.             jle     @@Term              ;if out of range
  141.             mov     bx, cx              ;else save in BX
  142.             mov     dx, cx              ; and DX
  143.             mov     cx, [Num]           ;# chars to copy
  144.             and     cx, cx
  145.             jle     @@Term              ;if Num out of range
  146.             sub     dx, cx              ;else if length > Num
  147.              jg     @@NumChars          ; move Num characters
  148.             mov     cx, bx              ;else move length chrs
  149.             jmp     short @@Move
  150. @@NumChars:
  151.             add     si, dx              ;start at length - Num
  152. @@Move:
  153.       rep movsb
  154. @@Term:
  155.             sub     al, al
  156.           stosb                         ;plant null terminator
  157.             pop     ax
  158.             pop     dx                  ;DX:AX->DestStr
  159.        @PopRegs     <ds, di, si>
  160.             ret
  161.        RIGHTSTR     endp
  162.  
  163. ;--------------------------------------------------------------------------
  164. ;        MidStr
  165. ;
  166. ; Copies Num characters from SrcStr to DestStr beginning at Start in
  167. ; SrcStr; returns pointer to DestStr.
  168. ;
  169. ; If Start is greater than the length of SrcStr, DestStr is returned
  170. ; null.  If Num is greater than the remainder of SrcStr, all characters
  171. ; from Start to the end of SrcStr are copied.  If either Start or Num
  172. ; is outside the range 1 to 32767, DestStr is returned null.
  173. ;--------------------------------------------------------------------------
  174.  
  175.          public     MIDSTR
  176.          MIDSTR     proc far
  177.  
  178.             arg     Num       :word               ;characters to copy
  179.             arg     Start     :word               ;start position
  180.             arg     SrcStr    :far ptr byte       ;source string
  181.             arg     DestStr   :far ptr byte       ;destination string
  182.  
  183.      ParmSize =     type Num + type Start + type SrcStr
  184.      ParmSize =     ParmSize + type DestStr
  185.  
  186.       @PushRegs     <si, di, ds>
  187.             mov     dx, ParmSize
  188.             les     di, [DestStr]
  189.            call     NullPtr
  190.            push     es                  ;save for return
  191.            push     di
  192.             mov     bx, [Start]
  193.             and     bx, bx
  194.             jle     @@Term              ;if Start <= 0
  195.             mov     dx, [Num]
  196.             and     dx, dx
  197.             jle     @@Term              ;if Num <= 0
  198.             lds     si, [SrcStr]        ;else load source
  199.            call     StrLen              ;CX = source length
  200.             and     cx, cx
  201.             jle     @@Term              ;if out of range
  202.             cmp     bx, cx
  203.              jg     @@Term              ;if Start > length
  204.             dec     bx                  ; adjust Start for 0,
  205.             sub     cx, bx              ; adjust length,
  206.             add     si, bx              ; and move pointer
  207.             cmp     dx, cx              ;if Num >= length
  208.             jge     @@Move              ; move length chars
  209.            xchg     cx, dx              ;else move Num chars
  210. @@Move:
  211.       rep movsb
  212. @@Term:
  213.             sub     al, al
  214.           stosb                         ;plant null terminator
  215.             pop     ax
  216.             pop     dx                  ;DX:AX->DestStr
  217.        @PopRegs     <ds, di, si>
  218.             ret
  219.          MIDSTR     endp
  220.  
  221. ;--------------------------------------------------------------------------
  222. ;         lJust
  223. ;
  224. ; Copies SrcStr to DestStr, left justified in a field of Size
  225. ; characters returns pointer to DestStr.
  226. ;
  227. ; DestStr is padded on the right with Chr.  Chr may be any character,
  228. ; including control codes.  Control codes behave as they normally would,
  229. ; either printing a graphics character or taking a specific action.
  230. ; If the length of SrcStr is greater than Size, SrcStr is truncated on
  231. ; the right.  If Size is outside the range 1 to 32767, DestStr is
  232. ; returned null.  If SrcStr is null, DestStr is filled with Size
  233. ; repetitions of Chr.
  234. ;--------------------------------------------------------------------------
  235.  
  236.          public     LJUST
  237.           LJUST     proc far
  238.  
  239.             arg     Chr       :word               ;fill character
  240.             arg     Size      :word               ;field Size
  241.             arg     SrcStr    :far ptr byte       ;source string
  242.             arg     DestStr   :far ptr byte       ;destination string
  243.  
  244.      ParmSize =     type Chr + type Size + type SrcStr
  245.      ParmSize =     ParmSize + type DestStr
  246.  
  247.       @PushRegs     <si, di, ds>
  248.             mov     dx, ParmSize
  249.             les     di, [DestStr]
  250.            call     NullPtr
  251.            push     es                  ;save for return
  252.            push     di
  253.             mov     bx, [Size]
  254.             and     bx, bx              ;if Size out of range
  255.             jle     @@Term              ; DestStr returned null
  256.             lds     si, [SrcStr]        ;load source string
  257.            call     StrLen              ;CX = source length
  258.             mov     al, byte ptr [Chr]  ;get fill character
  259.             and     cx, cx              ;if bad length
  260.             jle     @@PutChr            ; fill DestStr with Chr
  261.             cmp     cx, bx              ;if length >= Size
  262.             jge     @@SizeBytes         ; truncate source string
  263.             sub     bx, cx              ;else Size -= length
  264.             jmp     short @@Move
  265. @@SizeBytes:
  266.             mov     cx, bx              ;CX = Size
  267.             sub     bx, bx              ;0 for @@PutChr
  268. @@Move:
  269.       rep movsb
  270. @@PutChr:
  271.             mov     cx, bx              ;CX = Size
  272.       rep stosb                         ;fill DestStr with Chr
  273. @@Term:
  274.             sub     al, al
  275.           stosb                         ;plant null terminator
  276.             pop     ax
  277.             pop     dx                  ;DX:AX->DestStr
  278.        @PopRegs     <ds, di, si>
  279.             ret
  280.           LJUST     endp
  281.  
  282. ;--------------------------------------------------------------------------
  283. ;         rJust
  284. ;
  285. ; Copies SrcStr to DestStr, right justified in a field of Size
  286. ; characters returns pointer to DestStr.
  287. ;
  288. ; DestStr is padded on the left with Chr.  Chr may be any character,
  289. ; including control codes.  Control codes behave as they normally
  290. ; would, either printing a graphics character or taking a specific
  291. ; action.  If the length of SrcStr is greater than Size, SrcStr is
  292. ; truncated on the right.  If Size is outside the range 1 to 32767,
  293. ; DestStr is returned null.  If SrcStr is null, DestStr is filled
  294. ; with Size repetitions of Chr.
  295. ;--------------------------------------------------------------------------
  296.  
  297.          public     RJUST
  298.           RJUST     proc far
  299.  
  300.             arg     Chr       :word               ;fill character
  301.             arg     Size      :word               ;field Size
  302.             arg     SrcStr    :far ptr byte       ;source string
  303.             arg     DestStr   :far ptr byte       ;destination string
  304.  
  305.      ParmSize =     type Chr + type Size + type SrcStr
  306.      ParmSize =     ParmSize + type DestStr
  307.  
  308.       @PushRegs     <si, di, ds>
  309.             mov     dx, ParmSize
  310.             les     di, [DestStr]
  311.            call     NullPtr
  312.            push     es                  ;save for return
  313.            push     di
  314.             mov     bx, [Size]          ;get Size
  315.             and     bx, bx              ;if Size <= 0
  316.             jle     @@Term              ; DestStr returned null
  317.             mov     dx, bx              ;save Size
  318.             lds     si, [SrcStr]        ;load source string
  319.            call     StrLen              ;CX = source length
  320.             and     cx, cx              ;if <= 0
  321.             jle     @@PutChr            ; fill DestStr with Chr
  322.             sub     bx, cx              ;pad = Size - Length
  323.             jle     @@SizeBytes         ;truncate source
  324.            call     SameStr
  325.            lahf                         ;save ZF
  326.            call     OpenLeft
  327. @@PutChr:
  328.             mov     al, byte ptr [Chr]
  329.            xchg     cx, bx              ;CX = pad
  330.       rep stosb                         ;fill left end
  331.             and     bx, bx              ;check SrcStr length
  332.             jle     @@Term              ;if 0, all done
  333.            sahf                         ;restore ZF
  334.              jz     @@Same
  335.            xchg     cx, bx              ;CX = source length
  336.       rep movsb
  337. @@Same:
  338.             add     di, bx
  339.             sub     al, al
  340.           stosb                         ;plant null terminator
  341.             pop     ax
  342.             pop     dx                  ;DX:AX->DestStr
  343.        @PopRegs     <ds, di, si>
  344.             ret
  345. @@SizeBytes:
  346.             mov     cx, dx              ;CX = Size
  347.       rep movsb
  348. @@Term:
  349.             sub     al, al
  350.           stosb                         ;plant null terminator
  351.             pop     ax
  352.             pop     dx                  ;DX:AX->DestStr
  353.        @PopRegs     <ds, di, si>
  354.             ret
  355.           RJUST     endp
  356.  
  357. ;--------------------------------------------------------------------------
  358. ;         cJust
  359. ;
  360. ; Copies SrcStr to DestStr, centered in a field of Size characters;
  361. ; returns pointer to DestStr.
  362. ;
  363. ; DestStr is padded on the left and right with Chr.  Chr may be any
  364. ; character, with no provision for excluding ASCII control codes.
  365. ; If the total padding required to center SrcStr is odd, the extra
  366. ; character is added on the right.  If the length of SrcStr is greater
  367. ; than Size, SrcStr is truncated on the right. If Size is outside the
  368. ; range 1 to 32767, DestStr is returned null.  If SrcStr is null,
  369. ; DestStr is filled with Size repetitions of Chr.
  370. ;--------------------------------------------------------------------------
  371.  
  372.          public     CJUST
  373.           CJUST     proc far
  374.  
  375.             arg     Chr       :word               ;fill character
  376.             arg     Size      :word               ;field Size
  377.             arg     SrcStr    :far ptr byte       ;source string
  378.             arg     DestStr   :far ptr byte       ;destination string
  379.  
  380.      ParmSize =     type Chr + type Size + type SrcStr
  381.      ParmSize =     ParmSize + type DestStr
  382.  
  383.       @PushRegs     <si, di, ds>
  384.             mov     dx, ParmSize
  385.             les     di, [DestStr]
  386.            call     NullPtr
  387.            push     es                  ;save for return
  388.            push     di
  389.             lds     si, [SrcStr]        ;load source string
  390.            call     SameStr
  391.           pushf                         ;save ZF
  392.             mov     bx, [Size]
  393.             and     bx, bx              ;if Size out of range
  394.             jle     @@Term              ; DestStr returned null
  395.             mov     dx, bx              ;save Size
  396.             mov     al, byte ptr [Chr]
  397.            call     StrLen              ;CX = source length
  398.             and     cx, cx              ;if 0 < length < 32768
  399.              jg     @@LeftPad           ; calculate pad needed
  400.             sub     cx, cx              ;if length >= 32768
  401.             jmp     short @@LeftJust    ; fill dest with Chr
  402. @@LeftPad:
  403.             sub     bx, cx              ;if Size <= length
  404.             jle     @@SizeBytes         ; truncate source
  405.             shr     bx, 1               ;BX = Size / 2
  406.            lahf                         ;save remainder
  407.             mov     dx, bx              ;save quotient
  408.            call     OpenLeft
  409. @@LeftJust:
  410.            xchg     cx, bx              ;get left padding
  411.       rep stosb                         ;fill left end
  412.            xchg     cx, bx              ;get back source length
  413.            jcxz     @@Term              ;if no source, all done
  414.            popf
  415.              jz     @@NoMove            ;if source/dest identical
  416.       rep movsb
  417. @@NoMove:
  418.             add     di, cx
  419.             mov     cx, dx              ;CX = remaining dest
  420.            sahf                         ;restore remainder
  421.             adc     cx, bx
  422.       rep stosb                         ;fill right end
  423.             sub     al, al
  424.           stosb                         ;plant null terminator
  425.             pop     ax
  426.             pop     dx                  ;DX:AX->DestStr
  427.        @PopRegs     <ds, di, si>
  428.             ret
  429. @@SizeBytes:
  430.             mov     cx, dx              ;get back Size
  431.       rep movsb
  432. @@Term:
  433.             sub     al, al
  434.           stosb                         ;plant null terminator
  435.            popf                         ;clear from stack
  436.             pop     ax
  437.             pop     dx                  ;DX:AX->DestStr
  438.        @PopRegs     <ds, di, si>
  439.             ret
  440.           CJUST     endp
  441.  
  442. ;--------------------------------------------------------------------------
  443. ;         lTrim
  444. ;
  445. ; Copies SrcStr to DestStr with leading spaces and control characters
  446. ; removed.  Returns pointer to DestStr.
  447. ;--------------------------------------------------------------------------
  448.  
  449.          public     LTRIM
  450.           LTRIM     proc far
  451.  
  452.             arg     SrcStr    :far ptr byte       ;source string
  453.             arg     DestStr   :far ptr byte       ;destination string
  454.  
  455.      ParmSize =     type SrcStr + type DestStr
  456.  
  457.       @PushRegs     <si, di, ds>
  458.             mov     dx, ParmSize
  459.             les     di, [DestStr]
  460.            call     NullPtr
  461.            push     es                  ;save for return
  462.            push     di
  463.             lds     si, [SrcStr]
  464.            call     StrLen              ;CX = source length
  465.             and     cx, cx
  466.             jle     @@Term              ;if length out of range
  467. @@ChkLoop:
  468.           lodsb                         ;take a byte of source
  469.             and     al, al
  470.              jz     @@Term              ;if end-of-string null
  471.             dec     cx                  ;decrement length
  472.             cmp     al, 20h             ;char <= ASCII space?
  473.             jbe     @@ChkLoop           ;unsigned comparison
  474.             cmp     al, 7Fh
  475.              je     @@ChkLoop           ;if [Backspace]
  476.           stosb                         ;else store first byte
  477.       rep movsb                         ; and move the rest
  478. @@Term:
  479.             sub     al, al
  480.           stosb                         ;plant null terminator
  481.             pop     ax
  482.             pop     dx                  ;DX:AX->DestStr
  483.        @PopRegs     <ds, di, si>
  484.             ret
  485.           LTRIM     endp
  486.  
  487. ;--------------------------------------------------------------------------
  488. ;         rTrim
  489. ;
  490. ; Copies SrcStr to DestStr with trailing spaces and control characters
  491. ; removed.  Returns pointer to DestStr.
  492. ;--------------------------------------------------------------------------
  493.  
  494.          public     RTRIM
  495.           RTRIM     proc far
  496.  
  497.             arg     SrcStr    :far ptr byte       ;source string
  498.             arg     DestStr   :far ptr byte       ;destination string
  499.  
  500.      ParmSize =     type SrcStr + type DestStr
  501.  
  502.       @PushRegs     <si, di, ds>
  503.             mov     dx, ParmSize
  504.             les     di, [DestStr]
  505.            call     NullPtr
  506.            push     es                  ;save for return
  507.            push     di
  508.             lds     si, [SrcStr]
  509.            call     StrLen              ;CX = source length
  510.             and     cx, cx
  511.             jle     @@Term              ;if out of range
  512.             mov     bx, si              ;save SrcStr
  513.             add     si, cx              ;else bump pointer
  514.             dec     si                  ; and adjust for zero
  515.             inc     cx                  ;for @@ChkLoop
  516.             sub     ax, ax
  517.             std                         ;process strings "down"
  518. @@ChkLoop:
  519.             dec     cx
  520.           lodsb                         ;take a byte of source
  521.             cmp     al, 20h             ;char <= ASCII space?
  522.             jbe     @@ChkLoop           ;unsigned comparison
  523.             cmp     al, 7Fh
  524.              je     @@ChkLoop           ;if [Backspace]
  525. @@Move:
  526.             mov     si, bx
  527.             cld
  528.       rep movsb
  529. @@Term:
  530.             sub     al, al
  531.           stosb
  532.             pop     ax
  533.             pop     dx                  ;DX:AX->DestStr
  534.        @PopRegs     <ds, di, si>
  535.             ret
  536.           RTRIM     endp
  537.  
  538. ;--------------------------------------------------------------------------
  539. ;       ReplStr
  540. ;
  541. ; Replaces characters in DestStr with those from SrcStr.  Returns pointer
  542. ; to DestStr.
  543. ;
  544. ; If Start is greater than the length of DestStr, ScrStr is
  545. ; concatenated to DestStr.  If DestStr is null, SrcStr is copied
  546. ; to DestStr.  If Start or the length of SrcStr is outside the range
  547. ; 1 to 32767, DestStr is returned null.  If the length of DestStr
  548. ; will grow so that it crosses a segment boundary, DestStr is
  549. ; returned null.  If SrcStr and DestStr are identical, DestStr is
  550. ; returned unchanged.
  551. ;--------------------------------------------------------------------------
  552.  
  553.          public     REPLSTR
  554.         REPLSTR     proc far
  555.  
  556.             arg     Start     :word               ;start position
  557.             arg     SrcStr    :far ptr byte       ;source string
  558.             arg     DestStr   :far ptr byte       ;destination string
  559.  
  560.      ParmSize =     type Start + type SrcStr + type DestStr
  561.  
  562.       @PushRegs     <si, di, ds>
  563.             mov     dx, ParmSize
  564.             les     di, [DestStr]
  565.            call     NullPtr
  566.            push     es                  ;save for return
  567.            push     di
  568.             mov     ax, es              ;get ptr in DS:SI
  569.             mov     ds, ax              ; for StrLen()
  570.             mov     si, di
  571.            call     StrLen
  572.             mov     bx, cx              ;BX = DestStr length
  573.             lds     si, [SrcStr]        ;DS:SI->SrcStr
  574.            call     SameStr
  575.              jz     @@Exit              ;if strings identical
  576.            call     StrLen              ;CX = SrcStr length
  577.             and     cx, cx
  578.             jle     @@Term              ;if length <= 0
  579.             mov     dx, [Start]
  580.             and     dx, dx
  581.             jle     @@Term              ;if Start <= 0
  582.             dec     dx                  ;adjust for 0
  583.             cmp     dx, bx
  584.             jle     @@CheckSize         ;if Start <= length
  585.             mov     dx, bx              ;else Start = length
  586. @@CheckSize:
  587.             mov     ax, dx              ;AX =  start
  588.             add     ax, cx              ;AX += source length
  589.              jc     @@Term              ;if DestStr will wrap
  590.             add     ax, di              ;AX += DestStr
  591.              jc     @@Term              ;if DestStr will wrap
  592.             add     di, dx              ;DI->start
  593.             add     dx, cx              ;DX = Start + SrcStr len
  594.       rep movsb                         ;SrcStr=>DestStr
  595.             cmp     dx, bx
  596.              jg     @@Term              ;if DestStr grew
  597.             pop     ax
  598.             pop     dx                  ;DX:AX->DestStr
  599.        @PopRegs     <ds, di, si>
  600.             ret
  601. @@Term:
  602.             sub     al, al              ;terminate DestStr
  603.           stosb
  604. @@Exit:
  605.             pop     ax
  606.             pop     dx                  ;DX:AX->DestStr
  607.        @PopRegs     <ds, di, si>
  608.             ret
  609.         REPLSTR     endp
  610.  
  611. ;--------------------------------------------------------------------------
  612. ;        InsStr
  613. ;
  614. ; Inserts characters from SrcStr into DestStr.  Returns pointer to
  615. ; DestStr.
  616. ;
  617. ; If Start is greater than the length of DestStr, ScrStr is
  618. ; concatenated to DestStr.  If DestStr is null, SrcStr is copied
  619. ; to DestStr.  If Start or the length of SrcStr is outside the range
  620. ; 1 to 32767, DestStr is returned null.  If the length of DestStr
  621. ; will grow so that it crosses a segment boundary, DestStr is
  622. ; returned null.  If SrcStr and DestStr are identical, DestStr is
  623. ; returned unchanged.
  624. ;--------------------------------------------------------------------------
  625.  
  626.          public     INSSTR
  627.          INSSTR     proc far
  628.  
  629.             arg     Start     :word               ;start position
  630.             arg     SrcStr    :far ptr byte       ;source string
  631.             arg     DestStr   :far ptr byte       ;destination string
  632.  
  633.      ParmSize =     type Start + type SrcStr + type DestStr
  634.  
  635.       @PushRegs     <si, di, ds>
  636.             mov     dx, ParmSize
  637.             les     di, [DestStr]
  638.            call     NullPtr
  639.            push     es                  ;save for return
  640.            push     di
  641.             mov     ax, es              ;get ptr in DS:SI
  642.             mov     ds, ax              ; for StrLen()
  643.             mov     si, di
  644.            call     StrLen
  645.             mov     bx, cx              ;BX = DestStr length
  646.             lds     si, [SrcStr]        ;DS:SI->SrcStr
  647.            call     SameStr
  648.              jz     @@Exit              ;if strings identical
  649.             mov     dx, [Start]
  650.             and     dx, dx
  651.             jle     @@Term              ;if Start <= 0
  652.             dec     dx                  ;adjust for 0
  653.            call     StrLen              ;CX = SrcStr length
  654.             and     cx, cx
  655.             jle     @@Term              ;if length <= 0
  656.             cmp     dx, bx
  657.             jle     @@CheckSize         ;if Start <= dest length
  658.             mov     dx, bx              ;else Start = dest length
  659. @@CheckSize:
  660.             sub     bx, dx              ;BX = DestStr length to move
  661.               ;
  662.               ;     Check whether DestStr + DestStr length +
  663.               ;     SrcStr length will wrap around the segment.
  664.               ;
  665.             mov     ax, bx              ;AX =  dest length past Start
  666.             add     ax, cx              ;AX += source length
  667.              jc     @@Term              ;if DestStr will wrap
  668.             add     ax, di              ;AX += DestStr
  669.              jc     @@Term              ;if DestStr will wrap
  670.             add     di, dx              ;ES:DI->Start
  671.            xchg     cx, bx              ;CX=length/BX=distance
  672.            call     OpenLeft
  673.            xchg     cx, bx              ;CX = SrcStr length
  674. @@MoveSrc:
  675.       rep movsb                         ;SrcStr=>DestStr
  676.             pop     ax
  677.             pop     dx                  ;DX:AX->DestStr
  678.        @PopRegs     <ds, di, si>
  679.             ret
  680. @@Term:
  681.             sub     al, al
  682.           stosb
  683. @@Exit:
  684.             pop     ax
  685.             pop     dx                  ;DX:AX->DestStr
  686.        @PopRegs     <ds, di, si>
  687.             ret
  688.          INSSTR     endp
  689.  
  690. ;--------------------------------------------------------------------------
  691. ;      TemplStr
  692. ;
  693. ; Copies characters from SrcStr into DestStr.  Returns pointer to
  694. ; DestStr.
  695. ;
  696. ; At entry, DestStr points to a template to be filled in with
  697. ; characters from SrcStr and Chr is a marker in DestStr that
  698. ; indicates where those characters go.  Note that Chr must NOT
  699. ; occur in DestStr except as a marker for characters from SrcStr.
  700. ; For example, in the template "(999) 999-9999" Chr should be "9".
  701. ; Since " ", "(", ")", and "-" are part of the template, they
  702. ; would not be suitable as markers.  TemplStr moves characters
  703. ; from SrcStr to DestStr in order, continuing until SrcStr is
  704. ; exhausted or the end of DestStr is reached.  If SrcStr and
  705. ; DestStr are identical, DestStr is returned unchanged.
  706. ;--------------------------------------------------------------------------
  707.  
  708.          public     TEMPLSTR
  709.        TEMPLSTR     proc far
  710.  
  711.             arg     Chr       :word               ;flag character
  712.             arg     SrcStr    :far ptr byte       ;data string
  713.             arg     DestStr   :far ptr byte       ;format string
  714.  
  715.      ParmSize =     type Chr + type SrcStr + type DestStr
  716.  
  717.       @PushRegs     <si, di, ds>
  718.             mov     dx, ParmSize
  719.             les     di, [DestStr]
  720.            call     NullPtr
  721.            push     es                  ;save for return
  722.            push     di
  723.             lds     si, [SrcStr]        ;DS:SI->SrcStr
  724.            call     SameStr
  725.              jz     @@Exit              ;if strings identical
  726.             mov     ah, byte ptr [Chr]
  727.             sub     bl, bl              ;for cmp ES:[DI], 0
  728.             dec     di
  729. @@Loop:
  730.           lodsb
  731.             and     al, al
  732.              jz     @@Exit              ;if end of SrcStr
  733. @@ChkFlag:
  734.             inc     di
  735.             cmp     ah, es:[di]
  736.             jne     @@ChkEnd            ;if ES:[DI] != flag char
  737.           stosb                         ;else store char from SrcStr
  738.             dec     di
  739.             jmp     @@Loop              ; and continue
  740. @@ChkEnd:
  741.             cmp     bl, es:[di]
  742.             jne     @@ChkFlag           ;if not end of DestStr
  743. @@Exit:
  744.             pop     ax
  745.             pop     dx                  ;DX:AX->DestStr
  746.        @PopRegs     <ds, di, si>
  747.             ret
  748.        TEMPLSTR     endp
  749.  
  750. ;--------------------------------------------------------------------------
  751. ;       NullPtr
  752. ;
  753. ; This is an internal support routine, visible only within this module.
  754. ;
  755. ; Determines whether the destination pointer passed to a string routine
  756. ; is null.  If it is, NullPtr first pops the registers pushed by the
  757. ; string routine, then saves the return address of the __caller__ of
  758. ; the string routine, destroys the caller's stack frame, and returns
  759. ; to the caller with a null far pointer in DX:AX.  If the pointer is
  760. ; not null, NullPtr jumps back to the string routine.  At entry, the
  761. ; stack looks like this:
  762. ;
  763. ;                   +-----------+
  764. ;                   | Dest Segm |-\
  765. ;                   | Dest Offs |--\
  766. ;                   | Src  Segm |---\  Pushed by caller of
  767. ;                   | Src  Offs |---->  string routine.
  768. ;                   |     :     |---/   (DX = size of stack frame)
  769. ;                   |     :     |--/
  770. ;                   |Parameter X|-/
  771. ;                   |    CS     |----\ Far return to caller
  772. ;                   |    IP     |----/  of string routine.
  773. ;                   |    BP     |---\
  774. ;                   |    SI     |----\ Pushed by string routine.
  775. ;                   |    DI     |----/
  776. ;                   |    DS     |---/
  777. ;                   |Ret Address|----> Return addr of string routine.
  778. ;                   +-----------+
  779. ;
  780. ; Registers In                          Registers Out
  781. ; ----------------------------------    -----------------------------------
  782. ; ES:DI->destination string             DX:AX = 0L if ES:DI NULL
  783. ; DX = size of parms to pop
  784. ; BP-> saved BP on stack
  785. ; SP-> return addr of string routine
  786. ;--------------------------------------------------------------------------
  787.  
  788.         NullPtr     proc near
  789.             pop     bx                  ;BX = retn addr of string routine
  790.             mov     ax, es
  791.             and     ax, ax
  792.              jz     @@FarReturn         ;if segment is 0
  793.             and     di, di
  794.              jz     @@FarReturn         ;if offset is 0
  795.             jmp     bx                  ;ptr ok, return to string routine
  796. @@FarReturn:
  797.        @PopRegs     <ds, di, si>        ;pop regs saved by string routine
  798.             pop     bp                  ;restore BP
  799.             pop     cx                  ;CX = return IP \ to caller of
  800.             pop     bx                  ;BX = return CS / string routine
  801.             add     sp, dx              ;remove parms from stack
  802.             sub     ax, ax
  803.             mov     dx, ax              ;DX:AX = (char *) NULL
  804.            push     bx                  ;restore far return
  805.            push     cx                  ; to caller of string routine
  806.            retf                         ;to caller of string routine
  807.         NullPtr     endp
  808.  
  809. ;--------------------------------------------------------------------------
  810. ;      OpenLeft
  811. ;
  812. ; This is an internal support routine, visible only within this module.
  813. ;
  814. ; Opens space at the beginning of destination string so that,
  815. ; if destination and source strings are identical, routines that
  816. ; add to the beginning of the string can do so without overwriting
  817. ; any characters.
  818. ;
  819. ; Registers In                          Registers Out
  820. ; ----------------------------------    -----------------------------------
  821. ; BX = space to open in destination     none
  822. ; CX = length of source string
  823. ; DS:SI->source string
  824. ; ES:DI->destination string
  825. ;--------------------------------------------------------------------------
  826.  
  827.        OpenLeft     proc near
  828.            uses     bx, cx, ds, si, es, di
  829.  
  830.             add     di, cx              ;ES:DI->move from here
  831.             mov     si, es              ;source is end of
  832.             mov     ds, si              ; destination string
  833.             mov     si, di              ;DS:SI->move from here
  834.             add     di, bx              ;ES:DI->move to here
  835.             inc     cx                  ;move the null, too
  836.             std
  837.       rep movsb                         ;move CX chars BX places right
  838.             cld
  839.             ret
  840.        OpenLeft     endp
  841.  
  842. ;--------------------------------------------------------------------------
  843. ;       SameStr
  844. ;
  845. ; This is an internal support routine, visible only within this module.
  846. ;
  847. ; Check whether source and destination strings are identical.
  848. ;
  849. ; Registers In                          Registers Out
  850. ; ----------------------------------    -----------------------------------
  851. ; DS:SI->source string                  ZF = 1:  strings same
  852. ; ES:DI->destination string
  853. ;--------------------------------------------------------------------------
  854.  
  855.         SameStr     proc near
  856.            uses     ax, dx
  857.  
  858.             mov     ax, ds
  859.             mov     dx, es
  860.             xor     ax, dx
  861.             jnz     @@Diff
  862.             mov     ax, si
  863.             xor     ax, di
  864. @@Diff:
  865.             ret
  866.         SameStr     endp
  867.  
  868. ;--------------------------------------------------------------------------
  869. ;        StrLen
  870. ;
  871. ; This is an internal support routine, visible only within this module.
  872. ;
  873. ; Registers In                          Registers Out
  874. ; ----------------------------------    -----------------------------------
  875. ; DS:SI->string                         CX = length of string
  876. ;--------------------------------------------------------------------------
  877.  
  878.          StrLen     proc near
  879.            uses     ax, di, es
  880.  
  881.             cld
  882.             mov     ax, ds
  883.             mov     es, ax
  884.             mov     di, si
  885.             mov     cx, 0FFFFh          ;max scan (bytes)
  886.             sub     al, al              ;look for null byte
  887.     repne scasb
  888.             inc     cx
  889.             not     cx
  890.             ret
  891.          StrLen     endp
  892.  
  893.             end
  894.  
  895. ;**** EOF:  STRINGZ.ASM ****
  896. 
  897.