/* repsub.f -- translated by f2c (version 19980913).
   You must link the resulting object file with the libraries:
	-lf2c -lm   (in that order)
*/

#include "f2c.h"

/* Table of constant values */

static integer c__3 = 3;

/* $Procedure      REPSUB ( Replace one substring with another ) */
/* Subroutine */ int repsub_(char *in, integer *left, integer *right, char *
	string, char *out, ftnlen in_len, ftnlen string_len, ftnlen out_len)
{
    /* System generated locals */
    integer i__1, i__2;

    /* Builtin functions */
    integer i_len(char *, ftnlen);
    /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);

    /* Local variables */
    integer next, i__;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    integer inlen;
    extern integer sumai_(integer *, integer *);
    integer remain;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *, 
	    ftnlen);
    integer strlen, outlen;
    extern logical return_(void);
    integer end, use[3];

/* $ Abstract */

/*     Replace the substring (LEFT:RIGHT) with a string of any length. */

/* $ Copyright */

/*     Copyright (1995), California Institute of Technology. */
/*     U.S. Government sponsorship acknowledged. */

/* $ Required_Reading */

/*     None. */

/* $ Keywords */

/*     ASSIGNMENT */
/*     CHARACTER */
/*     STRING */

/* $ Declarations */
/* $ Brief_I/O */

/*     VARIABLE  I/O  DESCRIPTION */
/*     --------  ---  -------------------------------------------------- */
/*     IN         I   Input string. */
/*     LEFT, */
/*     RIGHT      I   Ends of substring to be replaced. */
/*     STRING     I   Replacement string. */
/*     OUT        O   Resulting string. */

/* $ Detailed_Input */

/*     IN         is an arbitrary character string. */

/*     LEFT, */
/*     RIGHT      are the ends of the substring to be replaced. */
/*                Legitimate substrings satisfy the following */
/*                conditions */

/*                    RIGHT > LEFT - 2 */
/*                    LEFT  > 1 */
/*                    RIGHT < LEN(STRING) + 1 */

/*                This allows users to refer to zero-length substrings */
/*                (null substrings) of IN. */

/*     STRING     is the replacement string. Essentially, the */
/*                substring (LEFT:RIGHT) is removed from the */
/*                input string, and STRING is inserted at the */
/*                point of removal. */

/* $ Detailed_Output */

/*     OUT        is the resulting string. OUT may overwrite IN. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) If RIGHT is one less than LEFT, the substring to */
/*        replace will be the null substring.  In this case, */
/*        STRING will be inserted between IN(:RIGHT) and IN(LEFT:). */

/*     2) If LEFT is smaller than one, the error SPICE(BEFOREBEGSTR) */
/*        is signalled. */

/*     3) If RIGHT is greater than the length of the input string, */
/*        the error SPICE(PASTENDSTR) is signalled. */

/*     4) If RIGHT is less than LEFT-1, the error SPICE(BADSUBSTR) */
/*        is signalled. */

/*     5) Whenever the output string is too small to hold the result, */
/*        the result is truncated on the right. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     Ideally, replacement could be done with simple concatenation, */

/*        OUT = IN(1:LEFT-1) // STRING // IN(RIGHT+1: ) */

/*     but the Fortran 77 standard makes this illegal for strings of */
/*     unknown length. */

/* $ Examples */

/*     A typical use for this routine might be to replace all */
/*     occurrences of one word in a string with another word. */
/*     For example, the following code fragment replaces every */
/*     occurrence of the word 'AND' with the word 'OR' in the */
/*     character string LINE. */

/*        LEFT = WDINDX ( LINE, 'AND' ) */

/*        DO WHILE ( LEFT .NE. 0 ) */
/*           CALL   REPSUB ( LINE, LEFT, LEFT+2, 'OR', LINE ) */
/*           LEFT = WDINDX ( LINE, 'AND' ) */
/*        END DO */

/*     This routine can also be used to insert substring between */
/*     two characters.  Consider the string: */

/*         IN   = 'The defendent,, was found innocent.' */

/*     to insert ' Emelda Marcos' between the first and second commas */
/*     determine the location of the pair ',,' */

/*        RIGHT = POS ( IN, ',,', 1 ) */
/*        LEFT  = RIGHT + 1 */

/*     then */

/*        CALL REPSUB ( IN, LEFT, RIGHT, ' Emelda Marcos', OUT ) */

/*     The output (OUT) will have the value: */

/*        'The defendent, Emelda Marcos, was found innocent.' */

/* $ Restrictions */

/*     The memory used by STRING and OUT must be disjoint. The memory */
/*     used by IN and OUT must be identical or disjoint. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     W.L. Taber     (JPL) */
/*     I.M. Underwood (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.2, 17-JUN-1999 (WLT) */

/*        Fixed example code fragment. */

/* -    SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 1.0.0, 24-AUG-1990 (WLT) (IMU) */

/* -& */
/* $ Index_Entries */

/*     replace one substring with another substring */

/* -& */

/*     SPICELIB functions */

/*     Local variables */

/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("REPSUB", (ftnlen)6);
    }

/*     Get the lengths of all the strings involved in this transaction. */

    inlen = i_len(in, in_len);
    strlen = i_len(string, string_len);
    outlen = i_len(out, out_len);

/*     Reject bad inputs. */

    if (*left < 1) {
	setmsg_("REPSUB error: LEFT (#) must not be less than 1.", (ftnlen)47)
		;
	errint_("#", left, (ftnlen)1);
	sigerr_("SPICE(BEFOREBEGSTR)", (ftnlen)19);
	chkout_("REPSUB", (ftnlen)6);
	return 0;
    } else if (*right > inlen) {
	setmsg_("REPSUB error: RIGHT (#) must not exceed length of IN (#).", (
		ftnlen)57);
	errint_("#", right, (ftnlen)1);
	errint_("#", &inlen, (ftnlen)1);
	sigerr_("SPICE(PASTENDSTR)", (ftnlen)17);
	chkout_("REPSUB", (ftnlen)6);
	return 0;
    } else if (*right < *left - 1) {
	setmsg_("REPSUB error: LEFT (#) must not exceed RIGHT+1 (# + 1). ", (
		ftnlen)56);
	errint_("#", left, (ftnlen)1);
	errint_("#", right, (ftnlen)1);
	sigerr_("SPICE(BADSUBSTR)", (ftnlen)16);
	chkout_("REPSUB", (ftnlen)6);
	return 0;
    }

/*     Consider three separate sections: */

/*        1) The front of the original string. */

/*        2) The replacement string. */

/*        3) The end of the original string. */

/*     Determine how much of each section to use in the output string. */
/*     REMAIN is the number of characters that will fit in the output */
/*     string. */

    remain = outlen;
/* Computing MIN */
    i__1 = remain, i__2 = *left - 1;
    use[0] = min(i__1,i__2);
    remain -= use[0];
    use[1] = min(remain,strlen);
    remain -= use[1];
/* Computing MIN */
    i__1 = remain, i__2 = inlen - *right;
    use[2] = min(i__1,i__2);

/*     Move the third section first. It gets moved back to front */
/*     or front to back, depending on whether the replacement string */
/*     is longer than the original substring. The main thing is to */
/*     avoid overwriting characters that have yet to be moved. */

    end = sumai_(use, &c__3);
    if (*left + strlen > *right) {
	next = end;
	for (i__ = use[2]; i__ >= 1; --i__) {
	    i__1 = *right + i__ - 1;
	    s_copy(out + (next - 1), in + i__1, (ftnlen)1, *right + i__ - 
		    i__1);
	    --next;
	}
    } else {
	next = *left + strlen;
	i__1 = use[2];
	for (i__ = 1; i__ <= i__1; ++i__) {
	    i__2 = *right + i__ - 1;
	    s_copy(out + (next - 1), in + i__2, (ftnlen)1, *right + i__ - 
		    i__2);
	    ++next;
	}
    }

/*     The first two sections can be moved directly to the front of */
/*     the output string. */

    next = 1;
    i__1 = use[0];
    for (i__ = 1; i__ <= i__1; ++i__) {
	*(unsigned char *)&out[next - 1] = *(unsigned char *)&in[i__ - 1];
	++next;
    }
    i__1 = use[1];
    for (i__ = 1; i__ <= i__1; ++i__) {
	*(unsigned char *)&out[next - 1] = *(unsigned char *)&string[i__ - 1];
	++next;
    }

/*     Pad with blanks, if the output string was not filled. */

    if (end < outlen) {
	i__1 = end;
	s_copy(out + i__1, " ", out_len - i__1, (ftnlen)1);
    }
    chkout_("REPSUB", (ftnlen)6);
    return 0;
} /* repsub_ */