From JLS@liverpool.ac.uk Mon Mar  9 14:46:08 1992
Received: from danpost2.uni-c.dk by dkuug.dk via EUnet with SMTP (5.64+/8+bit/IDA-1.2.8)
	id AA20950; Mon, 9 Mar 92 14:46:08 +0100
Received: from vm.uni-c.dk by danpost2.uni-c.dk (5.65/1.34)
	id AA16901; Mon, 9 Mar 92 13:44:56 GMT
Message-Id: <9203091344.AA16901@danpost2.uni-c.dk>
Received: from vm.uni-c.dk by vm.uni-c.dk (IBM VM SMTP V2R1) with BSMTP id 0669;
   Mon, 09 Mar 92 14:46:22 DNT
Received: from UKACRL.BITNET by vm.uni-c.dk (Mailer R2.07) with BSMTP id 6563;
 Mon, 09 Mar 92 14:46:18 DNT
Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 4783; Mon,
 09 Mar 92 13:36:22 GMT
Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 5258; Mon, 09
          Mar 92 13:36:02 GMT
Via:      UK.AC.LIV.IBM;  9 MAR 92 13:34:27 GMT
Received: from JLS@UK.AC.LIVERPOOL by MAILER(4.2.a);  9 Mar 1992 13:32:33 GM
Date:     Mon, 09 Mar 92 13:31:25 GMT
From: Lawrie Schonfelder <JLS@liverpool.ac.uk>
Subject:  is1539_1 d
To: SC22/WG5 members <SC22WG5@dkuug.dk>
X-Charset: ASCII
X-Char-Esc: 29

 ENDIF
 replace_ssc%chars => work
ENDFUNCTION replace_ssc

FUNCTION replace_scs(string,target,substring,every,back)
 type(VARYING_STRING)            :: replace_scs
 type(VARYING_STRING),INTENT(IN) :: string,substring
 CHARACTER(LEN=*),INTENT(IN)     :: target
 LOGICAL,INTENT(IN),OPTIONAL     :: every,back
 !  calculates the result string by the following actions:
 !  searches for occurences of target in string, and replaces these with
 !  substring. if back present with value true search is backward otherwise
 !  search is done forward. if every present with value true all accurences
 !  of target in string are replaced, otherwise only the first found is
 !  replaced. if target is not found the result is the same as string.
 LOGICAL                        :: dir_switch, rep_search
 CHARACTER,DIMENSION(:),POINTER :: work,temp,tget
 INTEGER                        :: ls,lt,lsub,ipos,ipow
 ls = LEN(string); lt = LEN(target); lsub = LEN(substring)
 IF(lt==0)THEN
   WRITE(*,*) " Zero length target in REPLACE"
   STOP
 ENDIF
 ALLOCATE(work(1:ls)); work = string%chars
 ALLOCATE(tget(1:lt))
 DO i=1,lt
   tget(i) = target(i:i)
 ENDDO
 IF( PRESENT(back) )THEN
   dir_switch = back
 ELSE
   dir_switch = .FALSE.
 ENDIF
 IF( PRESENT(every) )THEN
   rep_search = every
 ELSE
   rep_search = .FALSE.
 ENDIF
 IF( dir_switch )THEN ! backwards search
   ipos = ls-lt+1
   DO
     IF( ipos < 1 )EXIT ! search past start of string
     ! test for occurance of target in string at this position
     IF( ALL(string%chars(ipos:ipos+lt-1) == tget) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipos-1) = work(1:ipos-1)
       temp(ipos:ipos+lsub-1) = substring%chars
       temp(ipos+lsub:) = work(ipos+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos-lt+1
     ENDIF
     ipos=ipos-1
   ENDDO
 ELSE ! forward search
   ipos = 1; ipow = 1
   DO
     IF( ipos > ls-lt+1 )EXIT ! search past end of string
     ! test for occurance of target in string at this position
     IF( ALL(string%chars(ipos:ipos+lt-1) == tget) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipow-1) = work(1:ipow-1)
       temp(ipow:ipow+lsub-1) = substring%chars
       temp(ipow+lsub:) = work(ipow+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos+lt-1; ipow = ipow+lsub-1
     ENDIF
     ipos=ipos+1; ipow=ipow+1
   ENDDO
 ENDIF
 replace_scs%chars => work
ENDFUNCTION replace_scs

FUNCTION replace_scc(string,target,substring,every,back)
 type(VARYING_STRING)            :: replace_scc
 type(VARYING_STRING),INTENT(IN) :: string
 CHARACTER(LEN=*),INTENT(IN)     :: target,substring
 LOGICAL,INTENT(IN),OPTIONAL     :: every,back
 !  calculates the result string by the following actions:
 !  searches for occurences of target in string, and replaces these with
 !  substring. if back present with value true search is backward otherwise
 !  search is done forward. if every present with value true all accurences
 !  of target in string are replaced, otherwise only the first found is
 !  replaced. if target is not found the result is the same as string.
 LOGICAL                        :: dir_switch, rep_search
 CHARACTER,DIMENSION(:),POINTER :: work,temp,tget
 INTEGER                        :: ls,lt,lsub,ipos,ipow
 ls = LEN(string); lt = LEN(target); lsub = LEN(substring)
 IF(lt==0)THEN
   WRITE(*,*) " Zero length target in REPLACE"
   STOP
 ENDIF
 ALLOCATE(work(1:ls)); work = string%chars
 ALLOCATE(tget(1:lt))
 DO i=1,lt
   tget(i) = target(i:i)
 ENDDO
 IF( PRESENT(back) )THEN
   dir_switch = back
 ELSE
   dir_switch = .FALSE.
 ENDIF
 IF( PRESENT(every) )THEN
   rep_search = every
 ELSE
   rep_search = .FALSE.
 ENDIF
 IF( dir_switch )THEN ! backwards search
   ipos = ls-lt+1
   DO
     IF( ipos < 1 )EXIT ! search past start of string
     ! test for occurance of target in string at this position
     IF( ALL(string%chars(ipos:ipos+lt-1) == tget) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipos-1) = work(1:ipos-1)
       DO i=1,lsub
         temp(i+ipos-1) = substring(i:i)
       ENDDO
       temp(ipos+lsub:) = work(ipos+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos-lt+1
     ENDIF
     ipos=ipos-1
   ENDDO
 ELSE ! forward search
   ipos = 1; ipow = 1
   DO
     IF( ipos > ls-lt+1 )EXIT ! search past end of string
     ! test for occurance of target in string at this position
     IF( ALL(string%chars(ipos:ipos+lt-1) == tget) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipow-1) = work(1:ipow-1)
       DO i=1,lsub
         temp(i+ipow-1) = substring(i:i)
       ENDDO
       temp(ipow+lsub:) = work(ipow+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos+lt-1; ipow = ipow+lsub-1
     ENDIF
     ipos=ipos+1; ipow=ipow+1
   ENDDO
 ENDIF
 replace_scc%chars => work
ENDFUNCTION replace_scc

FUNCTION replace_css(string,target,substring,every,back)
 type(VARYING_STRING)            :: replace_css
 CHARACTER(LEN=*),INTENT(IN)     :: string
 type(VARYING_STRING),INTENT(IN) :: target,substring
 LOGICAL,INTENT(IN),OPTIONAL     :: every,back
 ! calculates the result string by the following actions:
 ! searches for occurences of target in string, and replaces these with
 ! substring. if back present with value true search is backward otherwise
 ! search is done forward. if every present with value true all accurences
 ! of target in string are replaced, otherwise only the first found is
 ! replaced. if target is not found the result is the same as string.
 LOGICAL                        :: dir_switch, rep_search
 CHARACTER,DIMENSION(:),POINTER :: work,temp,str
 INTEGER                        :: ls,lt,lsub,ipos,ipow
 ls = LEN(string); lt = LEN(target); lsub = LEN(substring)
 IF(lt==0)THEN
   WRITE(*,*) " Zero length target in REPLACE"
   STOP
 ENDIF
 ALLOCATE(work(1:ls)); ALLOCATE(str(1:ls))
 DO i=1,ls
   str(i) = string(i:i)
 ENDDO
 work = str
 IF( PRESENT(back) )THEN
   dir_switch = back
 ELSE
   dir_switch = .FALSE.
 ENDIF
 IF( PRESENT(every) )THEN
   rep_search = every
 ELSE
   rep_search = .FALSE.
 ENDIF
 IF( dir_switch )THEN ! backwards search
   ipos = ls-lt+1
   DO
     IF( ipos < 1 )EXIT ! search past start of string
     ! test for occurance of target in string at this position
     IF( ALL(str(ipos:ipos+lt-1) == target%chars) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipos-1) = work(1:ipos-1)
       temp(ipos:ipos+lsub-1) = substring%chars
       temp(ipos+lsub:) = work(ipos+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos-lt+1
     ENDIF
     ipos=ipos-1
   ENDDO
 ELSE ! forward search
   ipos = 1; ipow = 1
   DO
     IF( ipos > ls-lt+1 )EXIT ! search past end of string
     ! test for occurance of target in string at this position
     IF( ALL(str(ipos:ipos+lt-1) == target%chars) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipow-1) = work(1:ipow-1)
       temp(ipow:ipow+lsub-1) = substring%chars
       temp(ipow+lsub:) = work(ipow+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos+lt-1; ipow = ipow+lsub-1
     ENDIF
     ipos=ipos+1; ipow=ipow+1
   ENDDO
 ENDIF
 replace_css%chars => work
ENDFUNCTION replace_css

FUNCTION replace_csc(string,target,substring,every,back)
 type(VARYING_STRING)            :: replace_csc
 type(VARYING_STRING),INTENT(IN) :: target
 CHARACTER(LEN=*),INTENT(IN)     :: string,substring
 LOGICAL,INTENT(IN),OPTIONAL     :: every,back
 !  calculates the result string by the following actions:
 !  searches for occurences of target in string, and replaces these with
 !  substring. if back present with value true search is backward otherwise
 !  search is done forward. if every present with value true all accurences
 !  of target in string are replaced, otherwise only the first found is
 !  replaced. if target is not found the result is the same as string.
 LOGICAL                        :: dir_switch, rep_search
 CHARACTER,DIMENSION(:),POINTER :: work,temp,str
 INTEGER                        :: ls,lt,lsub,ipos,ipow
 ls = LEN(string); lt = LEN(target); lsub = LEN(substring)
 IF(lt==0)THEN
   WRITE(*,*) " Zero length target in REPLACE"
   STOP
 ENDIF
 ALLOCATE(work(1:ls)); ALLOCATE(str(1:ls))
 DO i=1,ls
   str(i) = string(i:i)
 ENDDO
 work = str
 IF( PRESENT(back) )THEN
   dir_switch = back
 ELSE
   dir_switch = .FALSE.
 ENDIF
 IF( PRESENT(every) )THEN
   rep_search = every
 ELSE
   rep_search = .FALSE.
 ENDIF
 IF( dir_switch )THEN ! backwards search
   ipos = ls-lt+1
   DO
     IF( ipos < 1 )EXIT ! search past start of string
     ! test for occurance of target in string at this position
     IF( ALL(str(ipos:ipos+lt-1) == target%chars) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipos-1) = work(1:ipos-1)
       DO i=1,lsub
         temp(i+ipos-1) = substring(i:i)
       ENDDO
       temp(ipos+lsub:) = work(ipos+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos-lt+1
     ENDIF
     ipos=ipos-1
   ENDDO
 ELSE ! forward search
   ipos = 1; ipow = 1
   DO
     IF( ipos > ls-lt+1 )EXIT ! search past end of string
     ! test for occurance of target in string at this position
     IF( ALL(str(ipos:ipos+lt-1) == target%chars) )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipow-1) = work(1:ipow-1)
       DO i=1,lsub
         temp(i+ipow-1) = substring(i:i)
       ENDDO
       temp(ipow+lsub:) = work(ipow+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos+lt-1; ipow = ipow+lsub-1
     ENDIF
     ipos=ipos+1; ipow=ipow+1
   ENDDO
 ENDIF
 replace_csc%chars => work
ENDFUNCTION replace_csc

FUNCTION replace_ccs(string,target,substring,every,back)
 type(VARYING_STRING)            :: replace_ccs
 type(VARYING_STRING),INTENT(IN) :: substring
 CHARACTER(LEN=*),INTENT(IN)     :: string,target
 LOGICAL,INTENT(IN),OPTIONAL     :: every,back
 !  calculates the result string by the following actions:
 !  searches for occurences of target in string, and replaces these with
 !  substring. if back present with value true search is backward otherwise
 !  search is done forward. if every present with value true all accurences
 !  of target in string are replaced, otherwise only the first found is
 !  replaced. if target is not found the result is the same as string.
 LOGICAL                        :: dir_switch, rep_search
 CHARACTER,DIMENSION(:),POINTER :: work,temp
 INTEGER                        :: ls,lt,lsub,ipos,ipow
 ls = LEN(string); lt = LEN(target); lsub = LEN(substring)
 IF(lt==0)THEN
   WRITE(*,*) " Zero length target in REPLACE"
   STOP
 ENDIF
 ALLOCATE(work(1:ls))
 DO i=1,ls
   work(i) = string(i:i)
 ENDDO
 IF( PRESENT(back) )THEN
   dir_switch = back
 ELSE
   dir_switch = .FALSE.
 ENDIF
 IF( PRESENT(every) )THEN
   rep_search = every
 ELSE
   rep_search = .FALSE.
 ENDIF
 IF( dir_switch )THEN ! backwards search
   ipos = ls-lt+1
   DO
     IF( ipos < 1 )EXIT ! search past start of string
     ! test for occurance of target in string at this position
     IF( string(ipos:ipos+lt-1) == target )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipos-1) = work(1:ipos-1)
       temp(ipos:ipos+lsub-1) = substring%chars
       temp(ipos+lsub:) = work(ipos+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos-lt+1
     ENDIF
     ipos=ipos-1
   ENDDO
 ELSE ! forward search
   ipos = 1; ipow = 1
   DO
     IF( ipos > ls-lt+1 )EXIT ! search past end of string
     ! test for occurance of target in string at this position
     IF( string(ipos:ipos+lt-1) == target )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipow-1) = work(1:ipow-1)
       temp(ipow:ipow+lsub-1) = substring%chars
       temp(ipow+lsub:) = work(ipow+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos+lt-1; ipow = ipow+lsub-1
     ENDIF
     ipos=ipos+1; ipow=ipow+1
   ENDDO
 ENDIF
 replace_ccs%chars => work
ENDFUNCTION replace_ccs

FUNCTION replace_ccc(string,target,substring,every,back)
 type(VARYING_STRING)            :: replace_ccc
 CHARACTER(LEN=*),INTENT(IN)     :: string,target,substring
 LOGICAL,INTENT(IN),OPTIONAL     :: every,back
 !  calculates the result string by the following actions:
 !  searches for occurences of target in string, and replaces these with
 !  substring. if back present with value true search is backward otherwise
 !  search is done forward. if every present with value true all accurences
 !  of target in string are replaced, otherwise only the first found is
 !  replaced. if target is not found the result is the same as string.
 LOGICAL                        :: dir_switch, rep_search
 CHARACTER,DIMENSION(:),POINTER :: work,temp
 INTEGER                        :: ls,lt,lsub,ipos,ipow
 ls = LEN(string); lt = LEN(target); lsub = LEN(substring)
 IF(lt==0)THEN
   WRITE(*,*) " Zero length target in REPLACE"
   STOP
 ENDIF
 ALLOCATE(work(1:ls))
 DO i=1,ls
   work(i) = string(i:i)
 ENDDO
 IF( PRESENT(back) )THEN
   dir_switch = back
 ELSE
   dir_switch = .FALSE.
 ENDIF
 IF( PRESENT(every) )THEN
   rep_search = every
 ELSE
   rep_search = .FALSE.
 ENDIF
 IF( dir_switch )THEN ! backwards search
   ipos = ls-lt+1
   DO
     IF( ipos < 1 )EXIT ! search past start of string
     ! test for occurance of target in string at this position
     IF( string(ipos:ipos+lt-1) == target )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipos-1) = work(1:ipos-1)
       DO i=1,lsub
         temp(i+ipos-1) = substring(i:i)
       ENDDO
       temp(ipos+lsub:) = work(ipos+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos-lt+1
     ENDIF
     ipos=ipos-1
   ENDDO
 ELSE ! forward search
   ipos = 1; ipow = 1
   DO
     IF( ipos > ls-lt+1 )EXIT ! search past end of string
     ! test for occurance of target in string at this position
     IF( string(ipos:ipos+lt-1) == target )THEN
       ! match found allocate space for string with this occurance of
       ! target replaced by substring
       ALLOCATE(temp(1:SIZE(work)+lsub-lt))
       ! copy work into temp replacing this occurance of target by
       ! substring
       temp(1:ipow-1) = work(1:ipow-1)
       DO i=1,lsub
         temp(i+ipow-1) = substring(i:i)
       ENDDO
       temp(ipow+lsub:) = work(ipow+lt:)
       DEALLOCATE(work)
       work => temp ! make new version of work point at the temp space
       IF(.NOT.rep_search)EXIT ! exit if only first replacement wanted
       ! move search and replacement positions over the effected positions
       ipos = ipos+lt-1; ipow = ipow+lsub-1
     ENDIF
     ipos=ipos+1; ipow=ipow+1
   ENDDO
 ENDIF
 replace_ccc%chars => work
ENDFUNCTION replace_ccc

!----- Remove procedures ----------------------------------------------------!
FUNCTION remove_s(string,start,finish)
 type(VARYING_STRING)            :: remove_s
 type(VARYING_STRING),INTENT(IN) :: string
 INTEGER,INTENT(IN),OPTIONAL     :: start
 INTEGER,INTENT(IN),OPTIONAL     :: finish
 !  returns as result the string produced by the actions
 !  removes the characters between start and finish from string reducing it in
 !  size by MAX(0,ABS(finish-start+1))
 !  if start < 1 or is missing then assumes start=1
 !  if finish > LEN(string) or is missing then assumes finish=LEN(string)
 CHARACTER,DIMENSION(:),POINTER :: arg_str
 INTEGER                        :: is,if,ls
 ls = LEN(string)
 IF (PRESENT(start)) THEN
   is = MAX(1,start)
 ELSE
   is = 1
 ENDIF
 IF (PRESENT(finish)) THEN
   if = MIN(ls,finish)
 ELSE
   if = ls
 ENDIF
 IF( if < is ) THEN  ! zero characters to be removed, string is unchanged
   ALLOCATE(arg_str(1:ls))
   arg_str = string%chars
 ELSE
   ALLOCATE(arg_str(1:ls-if+is-1) )
   arg_str(1:is-1) = string%chars(1:is-1)
   arg_str(is:) = string%chars(if+1:)
 ENDIF
 remove_s%chars => arg_str
ENDFUNCTION remove_s

FUNCTION remove_c(string,start,finish)
 type(VARYING_STRING)        :: remove_c
 CHARACTER(LEN=*),INTENT(IN) :: string
 INTEGER,INTENT(IN),OPTIONAL :: start
 INTEGER,INTENT(IN),OPTIONAL :: finish
 !  returns as result the string produced by the actions
 !  removes the characters between start and finish from string reducing it in
 !  size by MAX(0,ABS(finish-start+1))
 !  if start < 1 or is missing then assumes start=1
 !  if finish > LEN(string) or is missing then assumes finish=LEN(string)
 CHARACTER,DIMENSION(:),POINTER :: arg_str
 INTEGER                        :: is,if,ls
 ls = LEN(string)
 IF (PRESENT(start)) THEN
   is = MAX(1,start)
 ELSE
   is = 1
 ENDIF
 IF (PRESENT(finish)) THEN
   if = MIN(ls,finish)
 ELSE
   if = ls
 ENDIF
 IF( if < is ) THEN  ! zero characters to be removed, string is unchanged
   ALLOCATE(arg_str(1:ls))
   DO i=1,ls
     arg_str(i) = string(i:i)
   ENDDO
 ELSE
   ALLOCATE(arg_str(1:ls-if+is-1) )
   DO i=1,is-1
     arg_str(i) = string(i:i)
   ENDDO
   DO i=is,ls-if+is-1
     arg_str(i) = string(i-is+if+1:i-is+if+1)
   ENDDO
 ENDIF
 remove_c%chars => arg_str
ENDFUNCTION remove_c

!----- Extract procedures ---------------------------------------------------!
 FUNCTION extract_s(string,start,finish)
  type(VARYING_STRING),INTENT(IN) :: string
  INTEGER,INTENT(IN),OPTIONAL     :: start
  INTEGER,INTENT(IN),OPTIONAL     :: finish
  type(VARYING_STRING)            :: extract_s
  ! extracts the characters between start and finish from string  and
  ! delivers these as the result of the function, string is unchanged
  ! if start < 1 or is missing then it is treated as 1
  ! if finish > LEN(string) or is missing then it is treated as LEN(string)
  INTEGER                         :: is,if
  IF (PRESENT(start)) THEN
     is = MAX(1,start)
  ELSE
     is = 1
  ENDIF
  IF (PRESENT(finish)) THEN
     if = MIN(LEN(string),finish)
  ELSE
     if = LEN(string)
  ENDIF
  ALLOCATE(extract_s%chars(1:if-is+1))
  extract_s%chars = string%chars(is:if)
 ENDFUNCTION extract_s

 FUNCTION extract_c(string,start,finish)
  CHARACTER(LEN=*),INTENT(IN) :: string
  INTEGER,INTENT(IN),OPTIONAL :: start
  INTEGER,INTENT(IN),OPTIONAL :: finish
  type(VARYING_STRING)        :: extract_c
  ! extracts the characters between start and finish from character string and
  ! delivers these as the result of the function, string is unchanged
  ! if start < 1 or is missing then it is treated as 1
  ! if finish > LEN(string) or is missing then it is treated as LEN(string)
  INTEGER                      :: is,if
  IF (PRESENT(start)) THEN
     is = MAX(1,start)
  ELSE
     is = 1
  ENDIF
  IF (PRESENT(finish)) THEN
     if = MIN(LEN(string),finish)
  ELSE
     if = LEN(string)
  ENDIF
  ALLOCATE(extract_c%chars(1:if-is+1))
  DO i=is,if
    extract_c%chars(i-is+1) = string(i:i)
  ENDDO
 ENDFUNCTION extract_c

!----- INDEX procedures ------------------------------------------------------!
 FUNCTION index_ss(string,substring,back)
  type(VARYING_STRING),INTENT(IN) :: string,substring
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: index_ss
  ! returns the starting position in string of the substring
  ! scanning from the front or back depending on the logical argument back
  LOGICAL                         :: dir_switch
  INTEGER                         :: ls,lsub
  ls = LEN(string); lsub = LEN(substring)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    DO i = ls-lsub+1,1,-1
      IF( ALL(string%chars(i:i+lsub-1) == substring%chars) )THEN
        index_ss = i
        RETURN
      ENDIF
    ENDDO
    index_ss = 0
  ELSE ! forward search
    DO i = 1,ls-lsub+1
      IF( ALL(string%chars(i:i+lsub-1) == substring%chars) )THEN
        index_ss = i
        RETURN
      ENDIF
    ENDDO
    index_ss = 0
  ENDIF
 ENDFUNCTION index_ss

 FUNCTION index_sc(string,substring,back)
  type(VARYING_STRING),INTENT(IN) :: string
  CHARACTER(LEN=*),INTENT(IN)     :: substring
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: index_sc
  ! returns the starting position in string of the substring
  ! scanning from the front or back depending on the logical argument back
  LOGICAL                         :: dir_switch,matched
  INTEGER                         :: ls,lsub
  ls = LEN(string); lsub = LEN(substring)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF (dir_switch) THEN ! backwards search
    DO i = ls-lsub+1,1,-1
      matched = .TRUE.
      DO j = 1,lsub
        IF( string%chars(i+j-1) /= substring(j:j) )THEN
          matched = .FALSE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        index_sc = i
        RETURN
      ENDIF
    ENDDO
    index_sc = 0
  ELSE ! forward search
    DO i = 1,ls-lsub+1
      matched = .TRUE.
      DO j = 1,lsub
        IF( string%chars(i+j-1) /= substring(j:j) )THEN
          matched = .FALSE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        index_sc = i
        RETURN
      ENDIF
    ENDDO
    index_sc = 0
  ENDIF
 ENDFUNCTION index_sc

 FUNCTION index_cs(string,substring,back)
  CHARACTER(LEN=*),INTENT(IN)     :: string
  type(VARYING_STRING),INTENT(IN) :: substring
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: index_cs
  ! returns the starting position in string of the substring
  ! scanning from the front or back depending on the logical argument back
  LOGICAL                         :: dir_switch,matched
  INTEGER                         :: ls,lsub
  ls = LEN(string); lsub = LEN(substring)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    DO i = ls-lsub+1,1,-1
      matched = .TRUE.
      DO j = 1,lsub
        IF( string(i+j-1:i+j-1) /= substring%chars(j) )THEN
          matched = .FALSE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        index_cs = i
        RETURN
      ENDIF
    ENDDO
    index_cs = 0
  ELSE ! forward search
    DO i = 1,ls-lsub+1
      matched = .TRUE.
      DO j = 1,lsub
        IF( string(i+j-1:i+j-1) /= substring%chars(j) )THEN
          matched = .FALSE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        index_cs = i
        RETURN
      ENDIF
    ENDDO
    index_cs = 0
  ENDIF
 ENDFUNCTION index_cs

!----- SCAN procedures ------------------------------------------------------!
 FUNCTION scan_ss(string,set,back)
  type(VARYING_STRING),INTENT(IN) :: string,set
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: scan_ss
  ! returns the first position in string occupied by a character from
  ! the characters in set, scanning is forward or backwards depending on back
  LOGICAL                         :: dir_switch
  INTEGER                         :: ls
  ls = LEN(string)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    DO i = ls,1,-1
      IF( ANY( set%chars == string%chars(i) ) )THEN
        scan_ss = i
        RETURN
      ENDIF
    ENDDO
    scan_ss = 0
  ELSE ! forward search
    DO i = 1,ls
      IF( ANY( set%chars == string%chars(i) ) )THEN
        scan_ss = i
        RETURN
      ENDIF
    ENDDO
    scan_ss = 0
  ENDIF
 ENDFUNCTION scan_ss

 FUNCTION scan_sc(string,set,back)
  type(VARYING_STRING),INTENT(IN) :: string
  CHARACTER(LEN=*),INTENT(IN)     :: set
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: scan_sc
  ! returns the first position in string occupied by a character from
  ! the characters in set, scanning is forward or backwards depending on back
  LOGICAL                         :: dir_switch,matched
  INTEGER                         :: ls
  ls = LEN(string)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    DO i = ls,1,-1
      matched = .FALSE.
      DO j = 1,LEN(set)
        IF( string%chars(i) == set(j:j) )THEN
          matched = .TRUE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        scan_sc = i
        RETURN
      ENDIF
    ENDDO
    scan_sc = 0
  ELSE ! forward search
    DO i = 1,ls
      matched = .FALSE.
      DO j = 1,LEN(set)
        IF( string%chars(i) == set(j:j) )THEN
          matched = .TRUE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        scan_sc = i
        RETURN
      ENDIF
    ENDDO
    scan_sc = 0
  ENDIF
 ENDFUNCTION scan_sc

 FUNCTION scan_cs(string,set,back)
  CHARACTER(LEN=*),INTENT(IN)     :: string
  type(VARYING_STRING),INTENT(IN) :: set
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: scan_cs
  ! returns the first position in character string occupied by a character from
  ! the characters in set, scanning is forward or backwards depending on back
  LOGICAL                         :: dir_switch,matched
  INTEGER                         :: ls
  ls = LEN(string)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    DO i = ls,1,-1
      matched = .FALSE.
      DO j = 1,LEN(set)
        IF( string(i:i) == set%chars(j) )THEN
          matched = .TRUE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        scan_cs = i
        RETURN
      ENDIF
    ENDDO
    scan_cs = 0
  ELSE ! forward search
    DO i = 1,ls
      matched = .FALSE.
      DO j = 1,LEN(set)
        IF( string(i:i) == set%chars(j) )THEN
          matched = .TRUE.
          EXIT
        ENDIF
      ENDDO
      IF( matched )THEN
        scan_cs = i
        RETURN
      ENDIF
    ENDDO
    scan_cs = 0
  ENDIF
 ENDFUNCTION scan_cs

!----- VERIFY procedures ----------------------------------------------------!
 FUNCTION verify_ss(string,set,back)
  type(VARYING_STRING),INTENT(IN) :: string,set
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: verify_ss
  ! returns the first position in string not occupied by a character from
  ! the characters in set, scanning is forward or backwards depending on back
  LOGICAL                     :: dir_switch
  INTEGER                     :: ls
  ls = LEN(string)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    DO i = ls,1,-1
      IF( .NOT.(ANY( set%chars == string%chars(i))) )THEN
        verify_ss = i
        RETURN
      ENDIF
    ENDDO
    verify_ss = 0
  ELSE ! forward search
    DO i = 1,ls
      IF( .NOT.(ANY( set%chars == string%chars(i))) )THEN
        verify_ss = i
        RETURN
      ENDIF
    ENDDO
    verify_ss = 0
  ENDIF
 ENDFUNCTION verify_ss

 FUNCTION verify_sc(string,set,back)
  type(VARYING_STRING),INTENT(IN) :: string
  CHARACTER(LEN=*),INTENT(IN)     :: set
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: verify_sc
  ! returns the first position in string not occupied by a character from
  ! the characters in set, scanning is forward or backwards depending on back
  LOGICAL                     :: dir_switch
  INTEGER                     :: ls
  ls = LEN(string)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    back_string_search:DO i = ls,1,-1
      DO j = 1,LEN(set)
        IF( string%chars(i) == set(j:j) )CYCLE back_string_search
        ! cycle string search if string character found in set
      ENDDO
      ! string character not found in set index i is result
        verify_sc = i
        RETURN
    ENDDO back_string_search
    ! each string character found in set
    verify_sc = 0
  ELSE ! forward search
    frwd_string_search:DO i = 1,ls
      DO j = 1,LEN(set)
        IF( string%chars(i) == set(j:j) )CYCLE frwd_string_search
      ENDDO
        verify_sc = i
        RETURN
    ENDDO frwd_string_search
    verify_sc = 0
  ENDIF
 ENDFUNCTION verify_sc

 FUNCTION verify_cs(string,set,back)
  CHARACTER(LEN=*),INTENT(IN)     :: string
  type(VARYING_STRING),INTENT(IN) :: set
  LOGICAL,INTENT(IN),OPTIONAL     :: back
  INTEGER                         :: verify_cs
  ! returns the first position in icharacter string not occupied by a character
  ! from the characters in set, scanning is forward or backwards depending on
  ! back
  LOGICAL                     :: dir_switch
  INTEGER                     :: ls
  ls = LEN(string)
  IF( PRESENT(back) )THEN
    dir_switch = back
  ELSE
    dir_switch = .FALSE.
  ENDIF
  IF(dir_switch)THEN ! backwards search
    back_string_search:DO i = ls,1,-1
      DO j = 1,LEN(set)
        IF( string(i:i) == set%chars(j) )CYCLE back_string_search
      ENDDO
        verify_cs = i
        RETURN
    ENDDO back_string_search
    verify_cs = 0
  ELSE ! forward search
    frwd_string_search:DO i = 1,ls
      DO j = 1,LEN(set)
        IF( string(i:i) == set%chars(j) )CYCLE frwd_string_search
      ENDDO
        verify_cs = i
        RETURN
    ENDDO frwd_string_search
    verify_cs = 0
  ENDIF
 ENDFUNCTION verify_cs
